diff --git a/.dockerignore b/.dockerignore index f5cb53a0..19f7e1bb 100644 --- a/.dockerignore +++ b/.dockerignore @@ -11,6 +11,7 @@ coverage.* *.cover *.py,cover nosetests.xml +desktop.ini # Cache directories __pycache__/ @@ -37,7 +38,6 @@ __pypackages__/ # Packaging and distribution # ────────────────────────────────────────────────────────────────────────── build/ -dist/ dist-ssr/ *.egg *.egg-info/ diff --git a/.gitignore b/.gitignore index 790c0656..9129c5e3 100644 --- a/.gitignore +++ b/.gitignore @@ -64,8 +64,9 @@ htmlcov/ .pybuilder/ # Storefronts -.astro/ .nuxt/ +.next/ +next-env.d.ts # Celery celerybeat-schedule @@ -141,6 +142,10 @@ cypress/screenshots/ # JetBrains .idea/ +!.idea/icon.svg +!.idea/externalDependencies.xml +!.idea/evibes.iml +!.idea/evibes.ico # Microsoft *.suo diff --git a/.idea/evibes.ico b/.idea/evibes.ico new file mode 100644 index 00000000..f3ba783b Binary files /dev/null and b/.idea/evibes.ico differ diff --git a/.idea/evibes.iml b/.idea/evibes.iml new file mode 100644 index 00000000..307a37b8 --- /dev/null +++ b/.idea/evibes.iml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/externalDependencies.xml b/.idea/externalDependencies.xml new file mode 100644 index 00000000..66339880 --- /dev/null +++ b/.idea/externalDependencies.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/icon.svg b/.idea/icon.svg new file mode 100644 index 00000000..356c7ae0 --- /dev/null +++ b/.idea/icon.svg @@ -0,0 +1,25 @@ + + + + + + + + + + diff --git a/CODEOWNERS b/CODEOWNERS index 2a23c894..047718e6 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -4,8 +4,7 @@ README.md @fureunoir contact@fureunoir.com LICENSE @fureunoir contact@fureunoir.com -Dockerfile.app @fureunoir contact@fureunoir.com -Dockerfile.storefront @SaVBaD savbad@wiseless.xyz +Dockerfiles @@maintainer docker-compose.yml @@maintainer .gitignore @@maintainer .dockerignore @@maintainer @@ -13,14 +12,6 @@ nginx @@maintainer pyproject.toml @fureunoir contact@fureunoir.com poetry.lock @fureunoir contact@fureunoir.com -blog/ @fureunoir contact@fureunoir.com -core/ @fureunoir contact@fureunoir.com -evibes/ @fureunoir contact@fureunoir.com -payments/ @fureunoir contact@fureunoir.com -scripts/ @fureunoir contact@fureunoir.com -vibes_auth/ @fureunoir contact@fureunoir.com -storefront/ @SaVBaD savbad@wiseless.xyz - *.py @fureunoir contact@fureunoir.com *.bat @fureunoir contact@fureunoir.com *.sh @fureunoir contact@fureunoir.com @@ -31,5 +22,13 @@ storefront/ @SaVBaD savbad@wiseless.xyz *.mjs @SaVBaD savbad@wiseless.xyz *.cjs @SaVBaD savbad@wiseless.xyz *.vue @SaVBaD savbad@wiseless.xyz -*.astro @SaVBaD savbad@wiseless.xyz *.scss @SaVBaD savbad@wiseless.xyz + +blog/ @fureunoir contact@fureunoir.com +core/ @fureunoir contact@fureunoir.com +evibes/ @fureunoir contact@fureunoir.com +payments/ @fureunoir contact@fureunoir.com +scripts/ @fureunoir contact@fureunoir.com +vibes_auth/ @fureunoir contact@fureunoir.com + +storefront/ @SaVBaD savbad@wiseless.xyz \ No newline at end of file diff --git a/Dockerfiles/Dockerfile.app b/Dockerfiles/Dockerfile.app index 52042174..ef220880 100644 --- a/Dockerfiles/Dockerfile.app +++ b/Dockerfiles/Dockerfile.app @@ -26,6 +26,7 @@ RUN set -eux; \ graphviz-dev \ libgts-dev \ libpq5 \ + chrony \ graphviz \ binutils \ libproj-dev \ @@ -46,4 +47,4 @@ RUN chmod +x /usr/local/bin/app-entrypoint.sh COPY . . -ENTRYPOINT ["app-entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["/usr/bin/bash", "app-entrypoint.sh"] \ No newline at end of file diff --git a/Dockerfiles/Dockerfile.beat b/Dockerfiles/Dockerfile.beat index 84410630..f2f8684f 100644 --- a/Dockerfiles/Dockerfile.beat +++ b/Dockerfiles/Dockerfile.beat @@ -26,6 +26,7 @@ RUN set -eux; \ graphviz-dev \ libgts-dev \ libpq5 \ + chrony \ graphviz \ binutils \ libproj-dev \ @@ -46,4 +47,4 @@ RUN chmod +x /usr/local/bin/beat-entrypoint.sh COPY . . -ENTRYPOINT ["beat-entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["/usr/bin/bash", "beat-entrypoint.sh"] \ No newline at end of file diff --git a/Dockerfiles/Dockerfile.stock_updater b/Dockerfiles/Dockerfile.stock_updater new file mode 100644 index 00000000..39bbc5ba --- /dev/null +++ b/Dockerfiles/Dockerfile.stock_updater @@ -0,0 +1,50 @@ +# syntax=docker/dockerfile:1 +FROM python:3.12-bookworm +LABEL authors="fureunoir" + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + LANG=C.UTF-8 \ + DEBIAN_FRONTEND=noninteractive \ + PATH="/root/.local/bin:$PATH" + +WORKDIR /app + +RUN set -eux; \ + sed -i 's|https://deb.debian.org/debian|https://ftp.uk.debian.org/debian|g' /etc/apt/sources.list.d/debian.sources; \ + apt-get update; \ + apt-get install -y --no-install-recommends wget gnupg; \ + wget -qO - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -; \ + echo "deb http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" \ + > /etc/apt/sources.list.d/pgdg.list; \ + apt-get update; \ + apt-get install -y --no-install-recommends --fix-missing \ + build-essential \ + libpq-dev \ + gettext \ + libgettextpo-dev \ + graphviz-dev \ + libgts-dev \ + libpq5 \ + chrony \ + graphviz \ + binutils \ + libproj-dev \ + postgresql-client-17 \ + gdal-bin; \ + rm -rf /var/lib/apt/lists/*; \ + pip install --upgrade pip; \ + curl -sSL https://install.python-poetry.org | python3 + +COPY pyproject.toml pyproject.toml +COPY poetry.lock poetry.lock + +RUN poetry config virtualenvs.create false +RUN poetry install --extras="worker openai" --no-interaction --no-ansi + +COPY ./scripts/Docker/stock-updater-entrypoint.sh /usr/local/bin/stock-updater-entrypoint.sh +RUN chmod +x /usr/local/bin/stock-updater-entrypoint.sh + +COPY . . + +ENTRYPOINT ["/usr/bin/bash", "stock-updater-entrypoint.sh"] \ No newline at end of file diff --git a/Dockerfiles/Dockerfile.worker b/Dockerfiles/Dockerfile.worker index b34fcaf3..cb5234a9 100644 --- a/Dockerfiles/Dockerfile.worker +++ b/Dockerfiles/Dockerfile.worker @@ -26,6 +26,7 @@ RUN set -eux; \ graphviz-dev \ libgts-dev \ libpq5 \ + chrony \ graphviz \ binutils \ libproj-dev \ @@ -46,4 +47,4 @@ RUN chmod +x /usr/local/bin/worker-entrypoint.sh COPY . . -ENTRYPOINT ["worker-entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["/usr/bin/bash", "worker-entrypoint.sh"] \ No newline at end of file diff --git a/README.md b/README.md index 1c2d347e..5eacae06 100644 --- a/README.md +++ b/README.md @@ -44,10 +44,11 @@ extension. cd eVibes ``` -2. Choose the storefront. By default, `main` branch has Astro one. Skip this step if you're OK with Astro. +2. Choose the storefront. By default, `main` branch has no storefront included. +Skip this step if you're OK with that and plan to only use API or develop your own storefront. ```bash - git checkout storefront- + git checkout storefront- ``` 3. Generate your .env file. Check and confirm the contents afterward. diff --git a/blog/admin.py b/blog/admin.py index afafd660..7c6bf974 100644 --- a/blog/admin.py +++ b/blog/admin.py @@ -1,37 +1,40 @@ -from django.contrib import admin -from django_summernote.admin import SummernoteModelAdmin +from django.contrib.admin import ModelAdmin, register +from django_summernote.admin import SummernoteModelAdminMixin + +from core.admin import ActivationActionsMixin, FieldsetsMixin from .models import Post, PostTag -@admin.register(Post) -class PostAdmin(SummernoteModelAdmin): +@register(Post) +class PostAdmin(SummernoteModelAdminMixin, FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] list_display = ("title", "author", "slug", "created", "modified") list_filter = ("author", "tags", "created", "modified") - search_fields = ("title", "content") + search_fields = ("title", "content", "slug") filter_horizontal = ("tags",) date_hierarchy = "created" autocomplete_fields = ("author", "tags") - summernote_fields = ("content",) - - fieldsets = ( - ( - None, - { - "fields": ( - "author", - "title", - "content", - "file", - "tags", - ) - }, - ), + readonly_fields = ( + "uuid", + "slug", + "modified", + "created", ) + summernote_fields = ("content",) + general_fields = [ + "title", + "author", + "content", + "file", + ] + relation_fields = [ + "tags", + ] -@admin.register(PostTag) -class PostTagAdmin(admin.ModelAdmin): + +@register(PostTag) +class PostTagAdmin(ModelAdmin): list_display = ("tag_name", "name") search_fields = ("tag_name", "name") ordering = ("tag_name",) diff --git a/blog/locale/ar_AR/LC_MESSAGES/django.mo b/blog/locale/ar_AR/LC_MESSAGES/django.mo index 5300dfa5..f313ef1e 100644 Binary files a/blog/locale/ar_AR/LC_MESSAGES/django.mo and b/blog/locale/ar_AR/LC_MESSAGES/django.mo differ diff --git a/blog/locale/ar_AR/LC_MESSAGES/django.po b/blog/locale/ar_AR/LC_MESSAGES/django.po index f5a9d070..889822a7 100644 --- a/blog/locale/ar_AR/LC_MESSAGES/django.po +++ b/blog/locale/ar_AR/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,55 +17,52 @@ msgstr "" msgid "blog" msgstr "المدونة" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "عنوان المنشور" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "العنوان" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "المنشور" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "المنشورات" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "" "ملفات تخفيض السعر غير مدعومة Yer - استخدم محتوى تخفيض السعر بدلاً من ذلك!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "يجب توفير ملف ترميز أو محتوى ترميز مخفض - متنافيان" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "معرّف العلامة الداخلي لعلامة المنشور" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "اسم العلامة" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "اسم سهل الاستخدام لعلامة المنشور" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "اسم عرض العلامة" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "علامة المشاركة" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "علامات المشاركة" - -#~ msgid "eVibes Engine" -#~ msgstr "محرك eVibes" diff --git a/blog/locale/cs_CZ/LC_MESSAGES/django.mo b/blog/locale/cs_CZ/LC_MESSAGES/django.mo index e10d7a66..c507d90f 100644 Binary files a/blog/locale/cs_CZ/LC_MESSAGES/django.mo and b/blog/locale/cs_CZ/LC_MESSAGES/django.mo differ diff --git a/blog/locale/cs_CZ/LC_MESSAGES/django.po b/blog/locale/cs_CZ/LC_MESSAGES/django.po index e915c706..5ede773d 100644 --- a/blog/locale/cs_CZ/LC_MESSAGES/django.po +++ b/blog/locale/cs_CZ/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,57 +17,54 @@ msgstr "" msgid "blog" msgstr "Blog" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "Název příspěvku" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "Název" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "Příspěvek" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "Příspěvky" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "" "Soubory Markdown nejsou podporovány - místo toho použijte obsah Markdown!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" "musí být poskytnut soubor markdown nebo obsah markdown - vzájemně se " "vylučují." -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "interní identifikátor tagu pro tag příspěvku" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "Název štítku" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "Uživatelsky přívětivý název pro značku příspěvku" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "Zobrazení názvu štítku" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "Označení příspěvku" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "Štítky příspěvků" - -#~ msgid "eVibes Engine" -#~ msgstr "Motor eVibes" diff --git a/blog/locale/da_DK/LC_MESSAGES/django.mo b/blog/locale/da_DK/LC_MESSAGES/django.mo index e5c1f73b..af1ba23a 100644 Binary files a/blog/locale/da_DK/LC_MESSAGES/django.mo and b/blog/locale/da_DK/LC_MESSAGES/django.mo differ diff --git a/blog/locale/da_DK/LC_MESSAGES/django.po b/blog/locale/da_DK/LC_MESSAGES/django.po index 46d72f62..8b725448 100644 --- a/blog/locale/da_DK/LC_MESSAGES/django.po +++ b/blog/locale/da_DK/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,55 +17,52 @@ msgstr "" msgid "blog" msgstr "Blog" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "Indlæggets titel" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "Titel" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "Indlæg" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "Indlæg" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "Markdown-filer understøttes ikke - brug markdown-indhold i stedet!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" "en markdown-fil eller markdown-indhold skal leveres - gensidigt udelukkende" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "intern tag-identifikator for indlægs-tagget" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "Tag-navn" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "Brugervenligt navn til posttagget" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "Navn på tag-visning" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "Tag til indlæg" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "Tags til indlæg" - -#~ msgid "eVibes Engine" -#~ msgstr "eVibes-motor" diff --git a/blog/locale/de_DE/LC_MESSAGES/django.mo b/blog/locale/de_DE/LC_MESSAGES/django.mo index ca95544b..dc0b5861 100644 Binary files a/blog/locale/de_DE/LC_MESSAGES/django.mo and b/blog/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/blog/locale/de_DE/LC_MESSAGES/django.po b/blog/locale/de_DE/LC_MESSAGES/django.po index dedd31ad..9774aacc 100644 --- a/blog/locale/de_DE/LC_MESSAGES/django.po +++ b/blog/locale/de_DE/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,58 +17,55 @@ msgstr "" msgid "blog" msgstr "Blog" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "Titel des Beitrags" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "Titel" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "Beitrag" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "Beiträge" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "" "Markdown-Dateien werden nicht unterstützt - verwenden Sie stattdessen " "Markdown-Inhalte!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" "eine Markdown-Datei oder ein Markdown-Inhalt muss bereitgestellt werden - " "beide schließen sich gegenseitig aus" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "interner Tag-Bezeichner für den Post-Tag" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "Tag name" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "Benutzerfreundlicher Name für das Post-Tag" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "Tag-Anzeigename" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "Tag eintragen" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "Tags eintragen" - -#~ msgid "eVibes Engine" -#~ msgstr "eVibes Motor" diff --git a/blog/locale/en_GB/LC_MESSAGES/django.mo b/blog/locale/en_GB/LC_MESSAGES/django.mo index 4a846ade..b3b2a30b 100644 Binary files a/blog/locale/en_GB/LC_MESSAGES/django.mo and b/blog/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/blog/locale/en_GB/LC_MESSAGES/django.po b/blog/locale/en_GB/LC_MESSAGES/django.po index d7d73339..edb971dd 100644 --- a/blog/locale/en_GB/LC_MESSAGES/django.po +++ b/blog/locale/en_GB/LC_MESSAGES/django.po @@ -2,12 +2,12 @@ # Copyright (C) 2025 EGOR GORBUNOV # This file is distributed under the same license as the EVIBES package. # EGOR GORBUNOV , 2025. -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -21,61 +21,52 @@ msgstr "" msgid "blog" msgstr "Blog" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "Post's title" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "Title" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "Post" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "Posts" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "Markdown files are not supported yer - use markdown content instead!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" "a markdown file or markdown content must be provided - mutually exclusive" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "internal tag identifier for the post tag" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "Tag name" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "User-friendly name for the post tag" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "Tag display name" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "Post tag" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "Post tags" - -#~ msgid "eVibes Engine" -#~ msgstr "eVibes Engine" - -#~ msgid "(no content yet)" -#~ msgstr "(no content yet)" - -#~ msgid "rendered HTML" -#~ msgstr "Rendered HTML" diff --git a/blog/locale/en_US/LC_MESSAGES/django.mo b/blog/locale/en_US/LC_MESSAGES/django.mo index bf1dee8a..4f1d5f1f 100644 Binary files a/blog/locale/en_US/LC_MESSAGES/django.mo and b/blog/locale/en_US/LC_MESSAGES/django.mo differ diff --git a/blog/locale/en_US/LC_MESSAGES/django.po b/blog/locale/en_US/LC_MESSAGES/django.po index 9272d2ef..7d0d3dae 100644 --- a/blog/locale/en_US/LC_MESSAGES/django.po +++ b/blog/locale/en_US/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,55 +17,52 @@ msgstr "" msgid "blog" msgstr "Blog" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "Post's title" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "Title" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "Post" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "Posts" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "Markdown files are not supported yer - use markdown content instead!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" "a markdown file or markdown content must be provided - mutually exclusive" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "internal tag identifier for the post tag" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "Tag name" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "User-friendly name for the post tag" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "Tag display name" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "Post tag" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "Post tags" - -#~ msgid "eVibes Engine" -#~ msgstr "eVibes Engine" diff --git a/blog/locale/es_ES/LC_MESSAGES/django.mo b/blog/locale/es_ES/LC_MESSAGES/django.mo index 6f9496da..f993a3d2 100644 Binary files a/blog/locale/es_ES/LC_MESSAGES/django.mo and b/blog/locale/es_ES/LC_MESSAGES/django.mo differ diff --git a/blog/locale/es_ES/LC_MESSAGES/django.po b/blog/locale/es_ES/LC_MESSAGES/django.po index 0949d9d5..a09ee410 100644 --- a/blog/locale/es_ES/LC_MESSAGES/django.po +++ b/blog/locale/es_ES/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,57 +17,54 @@ msgstr "" msgid "blog" msgstr "Blog" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "Título del mensaje" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "Título" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "Publicar en" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "Puestos" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "" "No se admiten archivos Markdown - ¡utiliza contenido Markdown en su lugar!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" "se debe proporcionar un archivo markdown o contenido markdown - mutuamente " "excluyentes" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "identificador interno de la etiqueta post" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "Nombre de la etiqueta" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "Nombre fácil de usar para la etiqueta de la entrada" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "Nombre de la etiqueta" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "Etiqueta postal" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "Etiquetas" - -#~ msgid "eVibes Engine" -#~ msgstr "Motor eVibes" diff --git a/blog/locale/fr_FR/LC_MESSAGES/django.mo b/blog/locale/fr_FR/LC_MESSAGES/django.mo index 64081a77..ffbc0cc0 100644 Binary files a/blog/locale/fr_FR/LC_MESSAGES/django.mo and b/blog/locale/fr_FR/LC_MESSAGES/django.mo differ diff --git a/blog/locale/fr_FR/LC_MESSAGES/django.po b/blog/locale/fr_FR/LC_MESSAGES/django.po index f4d1c0df..6faa55df 100644 --- a/blog/locale/fr_FR/LC_MESSAGES/django.po +++ b/blog/locale/fr_FR/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,58 +17,55 @@ msgstr "" msgid "blog" msgstr "Blog" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "Titre du message" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "Titre" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "Poste" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "Postes" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "" "Les fichiers Markdown ne sont pas pris en charge - utilisez plutôt du " "contenu Markdown !" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" "un fichier markdown ou un contenu markdown doit être fourni - ils s'excluent " "mutuellement" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "identifiant interne de la balise post" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "Nom du jour" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "Nom convivial pour la balise post" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "Nom d'affichage de l'étiquette" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "Tag de poste" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "Tags de la poste" - -#~ msgid "eVibes Engine" -#~ msgstr "Moteur eVibes" diff --git a/blog/locale/hi_IN/LC_MESSAGES/django.mo b/blog/locale/hi_IN/LC_MESSAGES/django.mo index 0fc354f2..47c1f925 100644 Binary files a/blog/locale/hi_IN/LC_MESSAGES/django.mo and b/blog/locale/hi_IN/LC_MESSAGES/django.mo differ diff --git a/blog/locale/hi_IN/LC_MESSAGES/django.po b/blog/locale/hi_IN/LC_MESSAGES/django.po index cde6b30e..6b340223 100644 --- a/blog/locale/hi_IN/LC_MESSAGES/django.po +++ b/blog/locale/hi_IN/LC_MESSAGES/django.po @@ -2,12 +2,12 @@ # Copyright (C) 2025 EGOR GORBUNOV # This file is distributed under the same license as the EVIBES package. # EGOR GORBUNOV , 2025. -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -20,51 +20,51 @@ msgstr "" msgid "blog" msgstr "" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "" diff --git a/blog/locale/it_IT/LC_MESSAGES/django.mo b/blog/locale/it_IT/LC_MESSAGES/django.mo index 4fe49af5..beba2141 100644 Binary files a/blog/locale/it_IT/LC_MESSAGES/django.mo and b/blog/locale/it_IT/LC_MESSAGES/django.mo differ diff --git a/blog/locale/it_IT/LC_MESSAGES/django.po b/blog/locale/it_IT/LC_MESSAGES/django.po index 33bc4952..214c3409 100644 --- a/blog/locale/it_IT/LC_MESSAGES/django.po +++ b/blog/locale/it_IT/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,56 +17,53 @@ msgstr "" msgid "blog" msgstr "Blog" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "Titolo del post" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "Titolo" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "Posta" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "Messaggi" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "I file Markdown non sono supportati: usa invece i contenuti Markdown!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" "deve essere fornito un file markdown o un contenuto markdown - si escludono " "a vicenda" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "identificatore interno del tag post" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "Nome del tag" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "Nome intuitivo per il tag del post" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "Nome del tag" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "Post tag" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "Tag dei post" - -#~ msgid "eVibes Engine" -#~ msgstr "Motore eVibes" diff --git a/blog/locale/ja_JP/LC_MESSAGES/django.mo b/blog/locale/ja_JP/LC_MESSAGES/django.mo index b4077744..0bea06f8 100644 Binary files a/blog/locale/ja_JP/LC_MESSAGES/django.mo and b/blog/locale/ja_JP/LC_MESSAGES/django.mo differ diff --git a/blog/locale/ja_JP/LC_MESSAGES/django.po b/blog/locale/ja_JP/LC_MESSAGES/django.po index 2963679c..21d9d5bc 100644 --- a/blog/locale/ja_JP/LC_MESSAGES/django.po +++ b/blog/locale/ja_JP/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,58 +17,55 @@ msgstr "" msgid "blog" msgstr "ブログ" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "投稿タイトル" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "タイトル" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "ポスト" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "投稿" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "" "マークダウン・ファイルはサポートされていません - 代わりにマークダウン・コンテ" "ンツを使用してください!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" "マークダウン・ファイルまたはマークダウン・コンテンツを提供しなければならな" "い。" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "投稿タグの内部タグ識別子" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "タグ名" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "投稿タグのユーザーフレンドリーな名前" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "タグ表示名" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "投稿タグ" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "投稿タグ" - -#~ msgid "eVibes Engine" -#~ msgstr "eVibesエンジン" diff --git a/blog/locale/kk_KZ/LC_MESSAGES/django.mo b/blog/locale/kk_KZ/LC_MESSAGES/django.mo index 0fc354f2..47c1f925 100644 Binary files a/blog/locale/kk_KZ/LC_MESSAGES/django.mo and b/blog/locale/kk_KZ/LC_MESSAGES/django.mo differ diff --git a/blog/locale/kk_KZ/LC_MESSAGES/django.po b/blog/locale/kk_KZ/LC_MESSAGES/django.po index cde6b30e..6b340223 100644 --- a/blog/locale/kk_KZ/LC_MESSAGES/django.po +++ b/blog/locale/kk_KZ/LC_MESSAGES/django.po @@ -2,12 +2,12 @@ # Copyright (C) 2025 EGOR GORBUNOV # This file is distributed under the same license as the EVIBES package. # EGOR GORBUNOV , 2025. -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -20,51 +20,51 @@ msgstr "" msgid "blog" msgstr "" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "" diff --git a/blog/locale/nl_NL/LC_MESSAGES/django.mo b/blog/locale/nl_NL/LC_MESSAGES/django.mo index 479f9000..fad5266d 100644 Binary files a/blog/locale/nl_NL/LC_MESSAGES/django.mo and b/blog/locale/nl_NL/LC_MESSAGES/django.mo differ diff --git a/blog/locale/nl_NL/LC_MESSAGES/django.po b/blog/locale/nl_NL/LC_MESSAGES/django.po index 1a2069d2..e14bcdc1 100644 --- a/blog/locale/nl_NL/LC_MESSAGES/django.po +++ b/blog/locale/nl_NL/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,58 +17,55 @@ msgstr "" msgid "blog" msgstr "Blog" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "Titel van de post" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "Titel" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "Plaats" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "Berichten" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "" "Markdown-bestanden worden niet ondersteund - gebruik in plaats daarvan " "markdown-inhoud!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" "er moet een markdown-bestand of markdown-inhoud worden geleverd - wederzijds " "exclusief" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "interne tagidentifier voor de posttag" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "Tag naam" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "Gebruiksvriendelijke naam voor de posttag" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "Tag weergavenaam" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "Post tag" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "Post tags" - -#~ msgid "eVibes Engine" -#~ msgstr "eVibes motor" diff --git a/blog/locale/pl_PL/LC_MESSAGES/django.mo b/blog/locale/pl_PL/LC_MESSAGES/django.mo index 726aa952..135950e8 100644 Binary files a/blog/locale/pl_PL/LC_MESSAGES/django.mo and b/blog/locale/pl_PL/LC_MESSAGES/django.mo differ diff --git a/blog/locale/pl_PL/LC_MESSAGES/django.po b/blog/locale/pl_PL/LC_MESSAGES/django.po index 9c80ceda..3827d474 100644 --- a/blog/locale/pl_PL/LC_MESSAGES/django.po +++ b/blog/locale/pl_PL/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,57 +17,54 @@ msgstr "" msgid "blog" msgstr "Blog" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "Tytuł postu" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "Tytuł" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "Post" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "Posty" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "" "Pliki Markdown nie są obsługiwane - zamiast tego użyj zawartości Markdown!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" "należy dostarczyć plik markdown lub zawartość markdown - wzajemnie się " "wykluczające" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "wewnętrzny identyfikator tagu posta" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "Nazwa tagu" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "Przyjazna dla użytkownika nazwa tagu posta" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "Wyświetlana nazwa znacznika" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "Tag posta" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "Tagi postów" - -#~ msgid "eVibes Engine" -#~ msgstr "Silnik eVibes" diff --git a/blog/locale/pt_BR/LC_MESSAGES/django.mo b/blog/locale/pt_BR/LC_MESSAGES/django.mo index 52b3f93d..b9b9daa1 100644 Binary files a/blog/locale/pt_BR/LC_MESSAGES/django.mo and b/blog/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/blog/locale/pt_BR/LC_MESSAGES/django.po b/blog/locale/pt_BR/LC_MESSAGES/django.po index efa85afe..4b1addfc 100644 --- a/blog/locale/pt_BR/LC_MESSAGES/django.po +++ b/blog/locale/pt_BR/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,56 +17,53 @@ msgstr "" msgid "blog" msgstr "Blog" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "Título da postagem" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "Título" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "Postar" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "Publicações" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "" "Os arquivos markdown não são suportados - use conteúdo markdown em vez disso!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" "um arquivo ou conteúdo de markdown deve ser fornecido - mutuamente exclusivo" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "identificador de tag interno para a tag de postagem" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "Nome da etiqueta" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "Nome de fácil utilização para a tag de postagem" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "Nome de exibição da tag" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "Etiqueta de postagem" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "Tags de postagem" - -#~ msgid "eVibes Engine" -#~ msgstr "Motor eVibes" diff --git a/blog/locale/ro_RO/LC_MESSAGES/django.mo b/blog/locale/ro_RO/LC_MESSAGES/django.mo index 9df78c8a..1f2f9c95 100644 Binary files a/blog/locale/ro_RO/LC_MESSAGES/django.mo and b/blog/locale/ro_RO/LC_MESSAGES/django.mo differ diff --git a/blog/locale/ro_RO/LC_MESSAGES/django.po b/blog/locale/ro_RO/LC_MESSAGES/django.po index 13146549..2e6dce42 100644 --- a/blog/locale/ro_RO/LC_MESSAGES/django.po +++ b/blog/locale/ro_RO/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,57 +17,54 @@ msgstr "" msgid "blog" msgstr "Blog" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "Titlul postului" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "Titlul" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "Post" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "Mesaje" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "" "Fișierele Markdown nu sunt acceptate - utilizați în schimb conținut Markdown!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" "trebuie furnizat un fișier markdown sau conținut markdown - se exclud " "reciproc" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "identificator intern de etichetă pentru eticheta postului" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "Nume etichetă" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "Nume ușor de utilizat pentru eticheta postului" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "Nume afișare etichetă" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "Etichetă post" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "Etichete poștale" - -#~ msgid "eVibes Engine" -#~ msgstr "Motorul eVibes" diff --git a/blog/locale/ru_RU/LC_MESSAGES/django.mo b/blog/locale/ru_RU/LC_MESSAGES/django.mo index 8220775b..c310a3b1 100644 Binary files a/blog/locale/ru_RU/LC_MESSAGES/django.mo and b/blog/locale/ru_RU/LC_MESSAGES/django.mo differ diff --git a/blog/locale/ru_RU/LC_MESSAGES/django.po b/blog/locale/ru_RU/LC_MESSAGES/django.po index d1974a84..148f0d82 100644 --- a/blog/locale/ru_RU/LC_MESSAGES/django.po +++ b/blog/locale/ru_RU/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,58 +17,55 @@ msgstr "" msgid "blog" msgstr "Блог" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "Заголовок сообщения" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "Название" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "Пост" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "Посты" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "" "Файлы в формате Markdown не поддерживаются - используйте вместо них " "содержимое в формате Markdown!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "" "необходимо предоставить файл разметки или содержимое разметки - " "взаимоисключающие варианты" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "внутренний идентификатор тега для тега post" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "Название тега" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "Удобное для пользователя название тега поста" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "Отображаемое имя тега" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "Тэг поста" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "Тэги постов" - -#~ msgid "eVibes Engine" -#~ msgstr "Движок eVibes" diff --git a/blog/locale/zh_Hans/LC_MESSAGES/django.mo b/blog/locale/zh_Hans/LC_MESSAGES/django.mo index 7824700f..d034c894 100644 Binary files a/blog/locale/zh_Hans/LC_MESSAGES/django.mo and b/blog/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/blog/locale/zh_Hans/LC_MESSAGES/django.po b/blog/locale/zh_Hans/LC_MESSAGES/django.po index addf9a90..22e73742 100644 --- a/blog/locale/zh_Hans/LC_MESSAGES/django.po +++ b/blog/locale/zh_Hans/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,54 +17,51 @@ msgstr "" msgid "blog" msgstr "博客" -#: blog/models.py:17 +#: blog/models.py:36 msgid "post title" msgstr "帖子标题" -#: blog/models.py:17 +#: blog/models.py:36 msgid "title" msgstr "标题" -#: blog/models.py:64 +#: blog/models.py:83 msgid "post" msgstr "职位" -#: blog/models.py:65 +#: blog/models.py:84 msgid "posts" msgstr "职位" -#: blog/models.py:69 +#: blog/models.py:88 msgid "markdown files are not supported yet - use markdown content instead" msgstr "不支持 Markdown 文件,请使用 Markdown 内容!" -#: blog/models.py:71 +#: blog/models.py:90 msgid "" "a markdown file or markdown content must be provided - mutually exclusive" msgstr "必须提供标记符文件或标记符内容 - 相互排斥" -#: blog/models.py:82 +#: blog/models.py:122 msgid "internal tag identifier for the post tag" msgstr "职位标签的内部标签标识符" -#: blog/models.py:83 +#: blog/models.py:123 msgid "tag name" msgstr "标签名称" -#: blog/models.py:87 +#: blog/models.py:127 msgid "user-friendly name for the post tag" msgstr "方便用户使用的帖子标签名称" -#: blog/models.py:88 +#: blog/models.py:128 msgid "tag display name" msgstr "标签显示名称" -#: blog/models.py:96 +#: blog/models.py:136 msgid "post tag" msgstr "职位标签" -#: blog/models.py:97 +#: blog/models.py:137 msgid "post tags" msgstr "帖子标签" - -#~ msgid "eVibes Engine" -#~ msgstr "eVibes 引擎" diff --git a/blog/migrations/0001_initial.py b/blog/migrations/0001_initial.py index d9f6c5ed..231105f3 100644 --- a/blog/migrations/0001_initial.py +++ b/blog/migrations/0001_initial.py @@ -18,56 +18,113 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='PostTag', + name="PostTag", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('tag_name', models.CharField(help_text='internal tag identifier for the post tag', max_length=255, - verbose_name='tag name')), - ('name', models.CharField(help_text='user-friendly name for the post tag', max_length=255, unique=True, - verbose_name='tag display name')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "tag_name", + models.CharField( + help_text="internal tag identifier for the post tag", max_length=255, verbose_name="tag name" + ), + ), + ( + "name", + models.CharField( + help_text="user-friendly name for the post tag", + max_length=255, + unique=True, + verbose_name="tag display name", + ), + ), ], options={ - 'verbose_name': 'post tag', - 'verbose_name_plural': 'post tags', + "verbose_name": "post tag", + "verbose_name_plural": "post tags", }, ), migrations.CreateModel( - name='Post', + name="Post", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('title', models.CharField()), - ('content', markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name='content')), - ('file', models.FileField(blank=True, null=True, upload_to='posts/')), - ('slug', models.SlugField(allow_unicode=True)), - ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='posts', - to=settings.AUTH_USER_MODEL)), - ('tags', models.ManyToManyField(to='blog.posttag')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ("title", models.CharField()), + ("content", markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content")), + ("file", models.FileField(blank=True, null=True, upload_to="posts/")), + ("slug", models.SlugField(allow_unicode=True)), + ( + "author", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name="posts", to=settings.AUTH_USER_MODEL + ), + ), + ("tags", models.ManyToManyField(to="blog.posttag")), ], options={ - 'verbose_name': 'post', - 'verbose_name_plural': 'posts', + "verbose_name": "post", + "verbose_name_plural": "posts", }, ), ] diff --git a/blog/migrations/0002_alter_post_slug_alter_post_title.py b/blog/migrations/0002_alter_post_slug_alter_post_title.py index fbaf535f..e247c9ea 100644 --- a/blog/migrations/0002_alter_post_slug_alter_post_title.py +++ b/blog/migrations/0002_alter_post_slug_alter_post_title.py @@ -5,20 +5,21 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('blog', '0001_initial'), + ("blog", "0001_initial"), ] operations = [ migrations.AlterField( - model_name='post', - name='slug', - field=django_extensions.db.fields.AutoSlugField(allow_unicode=True, blank=True, editable=False, populate_from='title', unique=True), + model_name="post", + name="slug", + field=django_extensions.db.fields.AutoSlugField( + allow_unicode=True, blank=True, editable=False, populate_from="title", unique=True + ), ), migrations.AlterField( - model_name='post', - name='title', - field=models.CharField(help_text='post title', max_length=128, unique=True, verbose_name='title'), + model_name="post", + name="title", + field=models.CharField(help_text="post title", max_length=128, unique=True, verbose_name="title"), ), ] diff --git a/blog/migrations/0003_alter_post_tags.py b/blog/migrations/0003_alter_post_tags.py index 1929216c..c514b15c 100644 --- a/blog/migrations/0003_alter_post_tags.py +++ b/blog/migrations/0003_alter_post_tags.py @@ -4,15 +4,14 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('blog', '0002_alter_post_slug_alter_post_title'), + ("blog", "0002_alter_post_slug_alter_post_title"), ] operations = [ migrations.AlterField( - model_name='post', - name='tags', - field=models.ManyToManyField(blank=True, related_name='posts', to='blog.posttag'), + model_name="post", + name="tags", + field=models.ManyToManyField(blank=True, related_name="posts", to="blog.posttag"), ), ] diff --git a/blog/migrations/0004_post_content_ar_ar_post_content_cs_cz_and_more.py b/blog/migrations/0004_post_content_ar_ar_post_content_cs_cz_and_more.py new file mode 100644 index 00000000..4ccfcaec --- /dev/null +++ b/blog/migrations/0004_post_content_ar_ar_post_content_cs_cz_and_more.py @@ -0,0 +1,301 @@ +# Generated by Django 5.2 on 2025-06-29 13:09 + +import markdown_field.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("blog", "0003_alter_post_tags"), + ] + + operations = [ + migrations.AddField( + model_name="post", + name="content_ar_ar", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_cs_cz", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_da_dk", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_de_de", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_en_gb", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_en_us", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_es_es", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_fr_fr", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_hi_in", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_it_it", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_ja_jp", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_kk_kz", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_nl_nl", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_pl_pl", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_pt_br", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_ro_ro", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_ru_ru", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="content_zh_hans", + field=markdown_field.fields.MarkdownField(blank=True, null=True, verbose_name="content"), + ), + migrations.AddField( + model_name="post", + name="title_ar_ar", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_cs_cz", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_da_dk", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_de_de", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_en_gb", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_en_us", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_es_es", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_fr_fr", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_hi_in", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_it_it", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_ja_jp", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_kk_kz", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_nl_nl", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_pl_pl", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_pt_br", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_ro_ro", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_ru_ru", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + migrations.AddField( + model_name="post", + name="title_zh_hans", + field=models.CharField( + help_text="post title", + max_length=128, + null=True, + unique=True, + verbose_name="title", + ), + ), + ] diff --git a/blog/models.py b/blog/models.py index d47853e8..18878a5a 100644 --- a/blog/models.py +++ b/blog/models.py @@ -7,13 +7,32 @@ from markdown_field import MarkdownField from core.abstract import NiceModel -class Post(NiceModel): +class Post(NiceModel): # type: ignore [django-manager-missing] + """ + Represents a blog post model extending NiceModel. + + The Post class defines the structure and behavior of a blog post. It includes + attributes for author, title, content, optional file attachment, slug, + and associated tags. The class enforces constraints such as requiring either + content or a file attachment but not both simultaneously. It also supports + automatic slug generation based on the title. This model can be used in + a blogging platform to manage posts created by users. + + Attributes: + is_publicly_visible (bool): Specifies whether the post is visible to the public. + author (ForeignKey): A reference to the user who authored the post. + title (CharField): The title of the post. Must be unique and non-empty. + content (MarkdownField): The content of the post written in Markdown format. + file (FileField): An optional file attachment for the post. + slug (AutoSlugField): A unique, automatically generated slug based on the title. + tags (ManyToManyField): Tags associated with the post for categorization. + + """ + is_publicly_visible = True - author: ForeignKey = ForeignKey( - to="vibes_auth.User", on_delete=CASCADE, blank=False, null=False, related_name="posts" - ) - title: CharField = CharField( + author = ForeignKey(to="vibes_auth.User", on_delete=CASCADE, blank=False, null=False, related_name="posts") + title = CharField( unique=True, max_length=128, blank=False, null=False, help_text=_("post title"), verbose_name=_("title") ) content: MarkdownField = MarkdownField( @@ -53,9 +72,9 @@ class Post(NiceModel): blank=True, null=True, ) - file: FileField = FileField(upload_to="posts/", blank=True, null=True) - slug: AutoSlugField = AutoSlugField(populate_from="title", allow_unicode=True, unique=True, editable=False) - tags: ManyToManyField = ManyToManyField(to="blog.PostTag", blank=True, related_name="posts") + file = FileField(upload_to="posts/", blank=True, null=True) + slug = AutoSlugField(populate_from="title", allow_unicode=True, unique=True, editable=False) + tags = ManyToManyField(to="blog.PostTag", blank=True, related_name="posts") def __str__(self): return f"{self.title} | {self.author.first_name} {self.author.last_name}" @@ -73,16 +92,37 @@ class Post(NiceModel): class PostTag(NiceModel): - is_publicly_visible = True + """ + Represents a tag associated with a post. - tag_name: CharField = CharField( + The PostTag class is used to define and manage tags that can be assigned + to posts. These tags include an internal identifier and a user-friendly + display name. The class supports internationalization for both the internal + identifier and the display name. + + Attributes: + is_publicly_visible (bool): Determines if the tag is visible publicly. + tag_name (CharField): An internal tag identifier for the post's tag. It is a required + field with a maximum length of 255 characters. + name (CharField): A user-friendly, unique display name for the post's tag + with a maximum length of 255 characters. + + Meta: + verbose_name (str): Human-readable singular name of the PostTag model. + verbose_name_plural (str): Human-readable plural name of the PostTag model. + """ + + is_publicly_visible = True + posts: "Post" + + tag_name = CharField( blank=False, null=False, max_length=255, help_text=_("internal tag identifier for the post tag"), verbose_name=_("tag name"), ) - name: CharField = CharField( + name = CharField( max_length=255, help_text=_("user-friendly name for the post tag"), verbose_name=_("tag display name"), diff --git a/blog/translation.py b/blog/translation.py new file mode 100644 index 00000000..58f7ac02 --- /dev/null +++ b/blog/translation.py @@ -0,0 +1,9 @@ +from modeltranslation.decorators import register +from modeltranslation.translator import TranslationOptions + +from blog.models import Post + + +@register(Post) +class PostOptions(TranslationOptions): + fields = ("title", "content") diff --git a/blog/urls.py b/blog/urls.py index 1a6c8b34..ac04560f 100644 --- a/blog/urls.py +++ b/blog/urls.py @@ -3,6 +3,8 @@ from rest_framework.routers import DefaultRouter from blog.viewsets import PostViewSet +app_name = "blog" + payment_router = DefaultRouter() payment_router.register(prefix=r"posts", viewset=PostViewSet, basename="posts") diff --git a/blog/views.py b/blog/views.py index eea436a3..075719c8 100644 --- a/blog/views.py +++ b/blog/views.py @@ -1,3 +1,3 @@ import logging -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") diff --git a/blog/viewsets.py b/blog/viewsets.py index 8c30214c..deb26f23 100644 --- a/blog/viewsets.py +++ b/blog/viewsets.py @@ -8,6 +8,22 @@ from core.permissions import EvibesPermission class PostViewSet(ReadOnlyModelViewSet): + """ + Encapsulates operations for managing and retrieving Post entities in a read-only model view set. + + This class is tailored to handle Post objects that are active and allows filtration based on defined + filters. It integrates with Django's backend filtering system and ensures operations align with the + defined permissions. The view set also includes an additional "retrieve" permission configuration. + + Attributes: + serializer_class: Specifies the serializer to be used for Post objects. + permission_classes: Defines the permissions required to interact with this view set. + queryset: Determines the initial queryset, filtered to include only active Post objects. + filter_backends: Lists the backends to be used for filtering querysets. + filterset_class: Defines the set of filters used for filtering Post objects. + additional: Contains additional configuration, such as specific action permissions. + """ + serializer_class = PostSerializer permission_classes = (EvibesPermission,) queryset = Post.objects.filter(is_active=True) diff --git a/core/abstract.py b/core/abstract.py index 7ee83069..65f631e8 100644 --- a/core/abstract.py +++ b/core/abstract.py @@ -1,5 +1,4 @@ import uuid -from datetime import datetime from django.db.models import BooleanField, Model, UUIDField from django.utils.translation import gettext_lazy as _ @@ -7,32 +6,24 @@ from django_extensions.db.fields import CreationDateTimeField, ModificationDateT class NiceModel(Model): - id = None - uuid: uuid = UUIDField( # type: ignore + id: None = None + uuid = UUIDField( verbose_name=_("unique id"), help_text=_("unique id is used to surely identify any database object"), primary_key=True, default=uuid.uuid4, editable=False, ) - is_active: bool = BooleanField( # type: ignore + is_active = BooleanField( default=True, verbose_name=_("is active"), - help_text=_( - "if set to false, this object can't be seen by users without needed permission" - ), - ) - created: datetime = CreationDateTimeField( # type: ignore - _("created"), help_text=_("when the object first appeared on the database") - ) - modified: datetime = ModificationDateTimeField( # type: ignore - _("modified"), help_text=_("when the object was last modified") + help_text=_("if set to false, this object can't be seen by users without needed permission"), ) + created = CreationDateTimeField(_("created"), help_text=_("when the object first appeared on the database")) + modified = ModificationDateTimeField(_("modified"), help_text=_("when the object was last modified")) def save(self, **kwargs): - self.update_modified = kwargs.pop( - "update_modified", getattr(self, "update_modified", True) - ) + self.update_modified = kwargs.pop("update_modified", getattr(self, "update_modified", True)) super().save(**kwargs) class Meta: diff --git a/core/admin.py b/core/admin.py index 74b499a6..d7bfbcf0 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,21 +1,20 @@ from contextlib import suppress +from typing import ClassVar, Type from constance.admin import Config from constance.admin import ConstanceAdmin as BaseConstanceAdmin from django.apps import apps -from django.contrib import admin -from django.contrib.admin import ModelAdmin, TabularInline +from django.contrib.admin import ModelAdmin, TabularInline, action, register, site from django.contrib.gis.admin import GISModelAdmin +from django.contrib.messages import constants as messages from django.db.models import Model from django.utils.translation import gettext_lazy as _ from modeltranslation.translator import NotRegistered, translator from modeltranslation.utils import get_translation_fields from mptt.admin import DraggableMPTTAdmin -from evibes.settings import CONSTANCE_CONFIG - -from .forms import OrderForm, OrderProductForm, VendorForm -from .models import ( +from core.forms import OrderForm, OrderProductForm, VendorForm +from core.models import ( Address, Attribute, AttributeGroup, @@ -35,14 +34,21 @@ from .models import ( Vendor, Wishlist, ) +from evibes.settings import CONSTANCE_CONFIG class FieldsetsMixin: general_fields: list = [] relation_fields: list = [] - model: Model + model: ClassVar[Type[Model]] def get_fieldsets(self, request, obj=None): + if request: + pass + + if obj: + pass + fieldsets = [] def add_translations_fieldset(fss): @@ -52,9 +58,7 @@ class FieldsetsMixin: for orig in transoptions.local_fields: translation_fields += get_translation_fields(orig) if translation_fields: - fss = list(fss) + [ - (_("translations"), {"fields": translation_fields}) - ] + fss = list(fss) + [(_("translations"), {"fields": translation_fields})] return fss if self.general_fields: @@ -79,34 +83,37 @@ class FieldsetsMixin: return fieldsets -class BasicModelAdmin(ModelAdmin): - @admin.action(description=str(_("activate selected %(verbose_name_plural)s"))) - def activate_selected(self, request, queryset) -> str: - if request: - pass - queryset.update(is_active=True) - return str(_("%(verbose_name_plural)s activated successfully!")) +# noinspection PyUnresolvedReferences +class ActivationActionsMixin: + actions_on_top = True + actions_on_bottom = True + actions = [ + "delete_selected", + "activate_selected", + "deactivate_selected", + ] - @admin.action(description=str(_("deactivate selected %(verbose_name_plural)s"))) - def deactivate_selected(self, request, queryset) -> str: - if request: - pass - queryset.update(is_active=False) - return str(_("%(verbose_name_plural)s deactivated successfully.")) + @action(description=_("activate selected %(verbose_name_plural)s").lower(), permissions=["change"]) + def activate_selected(self, request, queryset): + try: + queryset.update(is_active=True) + self.message_user( + request=request, message=_("selected items have been activated.").lower(), level=messages.SUCCESS + ) - def get_actions(self, request): - actions = super().get_actions(request) - actions["activate_selected"] = ( - self.activate_selected, - "activate_selected", - str(_("activate selected %(verbose_name_plural)s")), - ) - actions["deactivate_selected"] = ( - self.deactivate_selected, - "deactivate_selected", - str(_("deactivate selected %(verbose_name_plural)s")), - ) - return actions + except Exception as e: + self.message_user(request=request, message=str(e), level=messages.ERROR) + + @action(description=_("deactivate selected %(verbose_name_plural)s").lower(), permissions=["change"]) + def deactivate_selected(self, request, queryset): + try: + queryset.update(is_active=False) + self.message_user( + request=request, message=_("selected items have been deactivated.").lower(), level=messages.SUCCESS + ) + + except Exception as e: + self.message_user(request=request, message=str(e), level=messages.ERROR) class AttributeValueInline(TabularInline): @@ -148,12 +155,7 @@ class OrderProductInline(TabularInline): icon = "fa-solid fa-boxes-packing" def get_queryset(self, request): - return ( - super() - .get_queryset(request) - .select_related("product") - .only("product__name") - ) + return super().get_queryset(request).select_related("product").only("product__name") class CategoryChildrenInline(TabularInline): @@ -167,9 +169,10 @@ class CategoryChildrenInline(TabularInline): icon = "fa-solid fa-leaf" -@admin.register(AttributeGroup) -class AttributeGroupAdmin(FieldsetsMixin, BasicModelAdmin): - model = AttributeGroup # type: ignore +@register(AttributeGroup) +class AttributeGroupAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = AttributeGroup # type: ignore [misc] list_display = ("name", "modified") search_fields = ("uuid", "name") readonly_fields = ("uuid", "modified", "created") @@ -178,9 +181,10 @@ class AttributeGroupAdmin(FieldsetsMixin, BasicModelAdmin): relation_fields = [] -@admin.register(Attribute) -class AttributeAdmin(FieldsetsMixin, BasicModelAdmin): - model = Attribute # type: ignore +@register(Attribute) +class AttributeAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = Attribute # type: ignore [misc] list_display = ("name", "group", "value_type", "modified") list_filter = ("value_type", "group", "is_active") search_fields = ("uuid", "name", "group__name") @@ -191,9 +195,10 @@ class AttributeAdmin(FieldsetsMixin, BasicModelAdmin): relation_fields = ["group", "categories"] -@admin.register(AttributeValue) -class AttributeValueAdmin(FieldsetsMixin, BasicModelAdmin): - model = AttributeValue # type: ignore +@register(AttributeValue) +class AttributeValueAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = AttributeValue # type: ignore [misc] list_display = ("attribute", "value", "modified") list_filter = ("attribute__group", "is_active") search_fields = ("uuid", "value", "attribute__name") @@ -204,35 +209,39 @@ class AttributeValueAdmin(FieldsetsMixin, BasicModelAdmin): relation_fields = ["attribute", "product"] -@admin.register(Category) -class CategoryAdmin(FieldsetsMixin, DraggableMPTTAdmin, BasicModelAdmin): - model = Category # type: ignore +@register(Category) +class CategoryAdmin(FieldsetsMixin, ActivationActionsMixin, DraggableMPTTAdmin): + # noinspection PyClassVar + model = Category list_display = ("indented_title", "parent", "is_active", "modified") + # noinspection PyUnresolvedReferences list_filter = ("is_active", "level", "created", "modified") search_fields = ("uuid", "name") inlines = [CategoryChildrenInline] autocomplete_fields = ["parent", "tags"] readonly_fields = ("slug", "uuid", "modified", "created") - general_fields = ["is_active", "name", "description", "image", "markup_percent"] + general_fields = ["is_active", "name", "description", "image", "markup_percent", "priority"] relation_fields = ["parent", "tags"] -@admin.register(Brand) -class BrandAdmin(FieldsetsMixin, BasicModelAdmin): - model = Brand # type: ignore +@register(Brand) +class BrandAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = Brand # type: ignore [misc] list_display = ("name",) list_filter = ("categories", "is_active") search_fields = ("uuid", "name", "categories__name") - readonly_fields = ("uuid", "modified", "created") + readonly_fields = ("uuid", "slug", "modified", "created") - general_fields = ["is_active", "name", "description"] + general_fields = ["is_active", "name", "description", "priority"] relation_fields = ["small_logo", "big_logo", "categories"] -@admin.register(Product) -class ProductAdmin(FieldsetsMixin, BasicModelAdmin): - model = Product # type: ignore +@register(Product) +class ProductAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = Product # type: ignore [misc] list_display = ( "name", "partnumber", @@ -246,8 +255,8 @@ class ProductAdmin(FieldsetsMixin, BasicModelAdmin): list_filter = ( "is_active", "is_digital", - ("tags", admin.RelatedOnlyFieldListFilter), - ("stocks__vendor", admin.RelatedOnlyFieldListFilter), + "stocks__vendor", + "tags__name", "created", "modified", ) @@ -255,7 +264,9 @@ class ProductAdmin(FieldsetsMixin, BasicModelAdmin): "name", "partnumber", "brand__name", + "brand__slug", "category__name", + "category__slug", "uuid", "slug", ) @@ -263,13 +274,14 @@ class ProductAdmin(FieldsetsMixin, BasicModelAdmin): autocomplete_fields = ("category", "brand", "tags") inlines = [AttributeValueInline, ProductImageInline, StockInline] - general_fields = ["is_active", "name", "partnumber", "is_active", "is_digital"] + general_fields = ["is_active", "name", "partnumber", "is_digital"] relation_fields = ["category", "brand", "tags"] -@admin.register(ProductTag) -class ProductTagAdmin(FieldsetsMixin, BasicModelAdmin): - model = ProductTag # type: ignore +@register(ProductTag) +class ProductTagAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = ProductTag # type: ignore [misc] list_display = ("tag_name",) search_fields = ("tag_name",) readonly_fields = ("uuid", "modified", "created") @@ -278,9 +290,10 @@ class ProductTagAdmin(FieldsetsMixin, BasicModelAdmin): relation_fields = [] -@admin.register(CategoryTag) -class CategoryTagAdmin(FieldsetsMixin, BasicModelAdmin): - model = CategoryTag # type: ignore +@register(CategoryTag) +class CategoryTagAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = CategoryTag # type: ignore [misc] list_display = ("tag_name",) search_fields = ("tag_name",) readonly_fields = ("uuid", "modified", "created") @@ -289,22 +302,24 @@ class CategoryTagAdmin(FieldsetsMixin, BasicModelAdmin): relation_fields = [] -@admin.register(Vendor) -class VendorAdmin(FieldsetsMixin, BasicModelAdmin): - model = Vendor # type: ignore +@register(Vendor) +class VendorAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = Vendor # type: ignore [misc] list_display = ("name", "markup_percent", "modified") list_filter = ("markup_percent", "is_active") search_fields = ("name",) readonly_fields = ("uuid", "modified", "created") form = VendorForm - general_fields = ["is_active", "name", "markup_percent", "authentication"] - relation_fields = [] + general_fields = ["is_active", "name", "markup_percent", "authentication", "b2b_auth_token"] + relation_fields = ["users"] -@admin.register(Feedback) -class FeedbackAdmin(FieldsetsMixin, BasicModelAdmin): - model = Feedback # type: ignore +@register(Feedback) +class FeedbackAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = Feedback # type: ignore [misc] list_display = ("order_product", "rating", "comment", "modified") list_filter = ("rating", "is_active") search_fields = ("order_product__product__name", "comment") @@ -314,9 +329,10 @@ class FeedbackAdmin(FieldsetsMixin, BasicModelAdmin): relation_fields = ["order_product"] -@admin.register(Order) -class OrderAdmin(FieldsetsMixin, BasicModelAdmin): - model = Order # type: ignore +@register(Order) +class OrderAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = Order # type: ignore [misc] list_display = ( "human_readable_id", "user", @@ -338,13 +354,14 @@ class OrderAdmin(FieldsetsMixin, BasicModelAdmin): inlines = [OrderProductInline] form = OrderForm - general_fields = ["is_active", "user", "status"] + general_fields = ["is_active", "user", "status", "notifications", "attributes", "buy_time"] relation_fields = ["promo_code", "billing_address", "shipping_address"] -@admin.register(OrderProduct) -class OrderProductAdmin(FieldsetsMixin, BasicModelAdmin): - model = OrderProduct # type: ignore +@register(OrderProduct) +class OrderProductAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = OrderProduct # type: ignore [misc] list_display = ("order", "product", "quantity", "buy_price", "status", "modified") list_filter = ("status",) search_fields = ("order__user__email", "product__name") @@ -355,9 +372,10 @@ class OrderProductAdmin(FieldsetsMixin, BasicModelAdmin): relation_fields = ["order", "product"] -@admin.register(PromoCode) -class PromoCodeAdmin(FieldsetsMixin, BasicModelAdmin): - model = PromoCode # type: ignore +@register(PromoCode) +class PromoCodeAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = PromoCode # type: ignore [misc] list_display = ( "code", "discount_percent", @@ -383,9 +401,10 @@ class PromoCodeAdmin(FieldsetsMixin, BasicModelAdmin): relation_fields = ["user"] -@admin.register(Promotion) -class PromotionAdmin(FieldsetsMixin, BasicModelAdmin): - model = Promotion # type: ignore +@register(Promotion) +class PromotionAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = Promotion # type: ignore [misc] list_display = ("name", "discount_percent", "modified") search_fields = ("name",) readonly_fields = ("uuid", "modified", "created") @@ -395,9 +414,10 @@ class PromotionAdmin(FieldsetsMixin, BasicModelAdmin): relation_fields = ["products"] -@admin.register(Stock) -class StockAdmin(FieldsetsMixin, BasicModelAdmin): - model = Stock # type: ignore +@register(Stock) +class StockAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = Stock # type: ignore [misc] list_display = ("product", "vendor", "sku", "quantity", "price", "modified") list_filter = ("vendor", "quantity") search_fields = ("product__name", "vendor__name", "sku") @@ -415,9 +435,10 @@ class StockAdmin(FieldsetsMixin, BasicModelAdmin): relation_fields = ["product", "vendor"] -@admin.register(Wishlist) -class WishlistAdmin(FieldsetsMixin, BasicModelAdmin): - model = Wishlist # type: ignore +@register(Wishlist) +class WishlistAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = Wishlist # type: ignore [misc] list_display = ("user", "modified") search_fields = ("user__email",) readonly_fields = ("uuid", "modified", "created") @@ -426,9 +447,10 @@ class WishlistAdmin(FieldsetsMixin, BasicModelAdmin): relation_fields = ["products"] -@admin.register(ProductImage) -class ProductImageAdmin(FieldsetsMixin, BasicModelAdmin): - model = ProductImage # type: ignore +@register(ProductImage) +class ProductImageAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + # noinspection PyClassVar + model = ProductImage # type: ignore [misc] list_display = ("alt", "product", "priority", "modified") list_filter = ("priority",) search_fields = ("alt", "product__name") @@ -439,9 +461,10 @@ class ProductImageAdmin(FieldsetsMixin, BasicModelAdmin): relation_fields = ["product"] -@admin.register(Address) +@register(Address) class AddressAdmin(FieldsetsMixin, GISModelAdmin): - model = Address # type: ignore + # noinspection PyClassVar + model = Address # type: ignore [misc] list_display = ("street", "city", "region", "country", "user") list_filter = ("country", "region") search_fields = ("street", "city", "postal_code", "user__email") @@ -501,8 +524,10 @@ class ConstanceConfig: _meta = Meta() -admin.site.unregister([Config]) # type: ignore -admin.site.register([ConstanceConfig], BaseConstanceAdmin) # type: ignore -admin.site.site_title = CONSTANCE_CONFIG["PROJECT_NAME"][0] # type: ignore -admin.site.site_header = "eVibes" -admin.site.index_title = CONSTANCE_CONFIG["PROJECT_NAME"][0] # type: ignore +# noinspection PyTypeChecker +site.unregister([Config]) +# noinspection PyTypeChecker +site.register([ConstanceConfig], BaseConstanceAdmin) # type: ignore [list-item] +site.site_title = CONSTANCE_CONFIG["PROJECT_NAME"][0] # type: ignore [assignment] +site.site_header = "eVibes" +site.index_title = CONSTANCE_CONFIG["PROJECT_NAME"][0] # type: ignore [assignment] diff --git a/core/api_urls.py b/core/api_urls.py index 3faadbc6..da873ef7 100644 --- a/core/api_urls.py +++ b/core/api_urls.py @@ -30,6 +30,8 @@ from core.viewsets import ( WishlistViewSet, ) +app_name = "core" + core_router = DefaultRouter() core_router.register(r"products", ProductViewSet, basename="products") core_router.register(r"orders", OrderViewSet, basename="orders") @@ -55,10 +57,26 @@ sitemaps = { urlpatterns = [ path("core/", include(core_router.urls)), path( - "sitemap.xml", sitemap_index, {"sitemaps": sitemaps, "sitemap_url_name": "sitemap-detail"}, name="sitemap-index" + "sitemap.xml", + sitemap_index, + { + "sitemaps": sitemaps, + "sitemap_url_name": "core:sitemap-detail", + }, + name="sitemap-index", + ), + path( + "sitemap-
.xml", + sitemap_detail, + {"sitemaps": sitemaps}, + name="sitemap-detail", + ), + path( + "sitemap-
-.xml", + sitemap_detail, + {"sitemaps": sitemaps}, + name="sitemap-detail", ), - path("sitemap-
.xml", sitemap_detail, {"sitemaps": sitemaps}, name="sitemap-detail"), - path("sitemap-
-.xml", sitemap_detail, {"sitemaps": sitemaps}, name="sitemap-detail"), path("download//", download_digital_asset_view, name="download_digital_asset"), path("search/", GlobalSearchView.as_view(), name="global_search"), path("app/cache/", CacheOperatorView.as_view(), name="cache_operator"), diff --git a/core/b2b_urls.py b/core/b2b_urls.py index 7d4c5e60..53a4f04c 100644 --- a/core/b2b_urls.py +++ b/core/b2b_urls.py @@ -5,6 +5,8 @@ from core.views import ( GlobalSearchView, ) +app_name = "core" + urlpatterns = [ path("search/", GlobalSearchView.as_view(), name="global_search"), path("orders/buy_as_business/", BuyAsBusinessView.as_view(), name="request_cursed_url"), diff --git a/core/docs/drf/viewsets.py b/core/docs/drf/viewsets.py index 6a2dbfd1..2eeead63 100644 --- a/core/docs/drf/viewsets.py +++ b/core/docs/drf/viewsets.py @@ -35,6 +35,7 @@ from core.serializers import ( WishlistDetailSerializer, WishlistSimpleSerializer, ) +from core.serializers.seo import SeoSnapshotSerializer from core.serializers.utility import AddressCreateSerializer, AddressSuggestionSerializer, DoFeedbackSerializer from payments.serializers import TransactionProcessSerializer @@ -122,28 +123,50 @@ ATTRIBUTE_VALUE_SCHEMA = { CATEGORY_SCHEMA = { "list": extend_schema( summary=_("list all categories (simple view)"), + description=_("list all categories (simple view)"), responses={status.HTTP_200_OK: CategorySimpleSerializer(many=True), **BASE_ERRORS}, ), "retrieve": extend_schema( summary=_("retrieve a single category (detailed view)"), + description=_("retrieve a single category (detailed view)"), responses={status.HTTP_200_OK: CategoryDetailSerializer(), **BASE_ERRORS}, ), "create": extend_schema( summary=_("create a category"), + description=_("create a category"), responses={status.HTTP_201_CREATED: CategoryDetailSerializer(), **BASE_ERRORS}, ), "destroy": extend_schema( summary=_("delete a category"), + description=_("delete a category"), responses={status.HTTP_204_NO_CONTENT: {}, **BASE_ERRORS}, ), "update": extend_schema( summary=_("rewrite an existing category saving non-editables"), + description=_("rewrite an existing category saving non-editables"), responses={status.HTTP_200_OK: CategoryDetailSerializer(), **BASE_ERRORS}, ), "partial_update": extend_schema( summary=_("rewrite some fields of an existing category saving non-editables"), + description=_("rewrite some fields of an existing category saving non-editables"), responses={status.HTTP_200_OK: CategoryDetailSerializer(), **BASE_ERRORS}, ), + "seo": extend_schema( + summary=_("SEO Meta Snapshot"), + description=_("returns a snapshot of the category's SEO meta data"), + parameters=[ + OpenApiParameter( + name="lookup", + location="path", + description=_("Category UUID or slug"), + type=str, + ), + ], + responses={ + status.HTTP_200_OK: SeoSnapshotSerializer(), + **BASE_ERRORS, + }, + ), } ORDER_SCHEMA = { @@ -347,6 +370,7 @@ ATTRIBUTES_DESC = _( PRODUCT_SCHEMA = { "list": extend_schema( summary=_("list all products (simple view)"), + description=_("list all products (simple view)"), parameters=[ OpenApiParameter( name="uuid", @@ -439,6 +463,7 @@ PRODUCT_SCHEMA = { ), "retrieve": extend_schema( summary=_("retrieve a single product (detailed view)"), + description=_("retrieve a single product (detailed view)"), parameters=[ OpenApiParameter( name="lookup_value", @@ -454,6 +479,7 @@ PRODUCT_SCHEMA = { ), "create": extend_schema( summary=_("create a product"), + description=_("create a product"), responses={ status.HTTP_201_CREATED: ProductDetailSerializer(), **BASE_ERRORS, @@ -461,6 +487,7 @@ PRODUCT_SCHEMA = { ), "update": extend_schema( summary=_("rewrite an existing product, preserving non-editable fields"), + description=_("rewrite an existing product, preserving non-editable fields"), parameters=[ OpenApiParameter( name="lookup", @@ -476,6 +503,7 @@ PRODUCT_SCHEMA = { ), "partial_update": extend_schema( summary=_("update some fields of an existing product, preserving non-editable fields"), + description=_("update some fields of an existing product, preserving non-editable fields"), parameters=[ OpenApiParameter( name="lookup", @@ -491,6 +519,7 @@ PRODUCT_SCHEMA = { ), "destroy": extend_schema( summary=_("delete a product"), + description=_("delete a product"), parameters=[ OpenApiParameter( name="lookup", @@ -506,6 +535,7 @@ PRODUCT_SCHEMA = { ), "feedbacks": extend_schema( summary=_("lists all permitted feedbacks for a product"), + description=_("lists all permitted feedbacks for a product"), parameters=[ OpenApiParameter( name="lookup", @@ -519,6 +549,22 @@ PRODUCT_SCHEMA = { **BASE_ERRORS, }, ), + "seo": extend_schema( + summary=_("SEO Meta Snapshot"), + description=_("returns a snapshot of the product's SEO meta data"), + parameters=[ + OpenApiParameter( + name="lookup", + location="path", + description=_("Product UUID or slug"), + type=str, + ), + ], + responses={ + status.HTTP_200_OK: SeoSnapshotSerializer(), + **BASE_ERRORS, + }, + ), } ADDRESS_SCHEMA = { diff --git a/core/elasticsearch/__init__.py b/core/elasticsearch/__init__.py index 94df9650..cf6ebbfd 100644 --- a/core/elasticsearch/__init__.py +++ b/core/elasticsearch/__init__.py @@ -15,19 +15,15 @@ SMART_FIELDS = [ "name^6", "name.ngram^5", "name.phonetic", - "title^4", "title.ngram^3", "title.phonetic", - "description^2", "description.ngram", "description.phonetic", - "brand__name^3", "brand__name.ngram", "brand__name.auto", - "category__name^2", "category__name.ngram", "category__name.auto", @@ -71,7 +67,6 @@ functions = [ "missing": 0, }, }, - # category-level boost when searching for categories { "filter": Q("term", **{"_index": "categories"}), @@ -82,7 +77,6 @@ functions = [ "missing": 0, }, }, - # brand-level boost when searching for brands { "filter": Q("term", **{"_index": "brands"}), @@ -191,8 +185,8 @@ def process_query(query: str = "", request: Request | None = None) -> dict[str, results[idx].append(hit_result) return results - except NotFoundError: - raise Http404 + except NotFoundError as nfe: + raise Http404 from nfe LANGUAGE_ANALYZER_MAP = { diff --git a/core/elasticsearch/documents.py b/core/elasticsearch/documents.py index dceadfe9..cb6af311 100644 --- a/core/elasticsearch/documents.py +++ b/core/elasticsearch/documents.py @@ -12,13 +12,9 @@ class _BaseDoc(ActiveOnlyMixin, Document): analyzer="standard", fields={ "raw": fields.KeywordField(ignore_above=256), - "ngram": fields.TextField( - analyzer="name_ngram", search_analyzer="query_lc" - ), + "ngram": fields.TextField(analyzer="name_ngram", search_analyzer="query_lc"), "phonetic": fields.TextField(analyzer="name_phonetic"), - "auto": fields.TextField( - analyzer="autocomplete", search_analyzer="autocomplete_search" - ), + "auto": fields.TextField(analyzer="autocomplete", search_analyzer="autocomplete_search"), }, ) description = fields.TextField( @@ -26,13 +22,9 @@ class _BaseDoc(ActiveOnlyMixin, Document): analyzer="standard", fields={ "raw": fields.KeywordField(ignore_above=256), - "ngram": fields.TextField( - analyzer="name_ngram", search_analyzer="query_lc" - ), + "ngram": fields.TextField(analyzer="name_ngram", search_analyzer="query_lc"), "phonetic": fields.TextField(analyzer="name_phonetic"), - "auto": fields.TextField( - analyzer="autocomplete", search_analyzer="autocomplete_search" - ), + "auto": fields.TextField(analyzer="autocomplete", search_analyzer="autocomplete_search"), }, ) slug = fields.KeywordField(attr="slug", index=False) diff --git a/core/filters.py b/core/filters.py index d2abb6bf..996a28a6 100644 --- a/core/filters.py +++ b/core/filters.py @@ -32,7 +32,7 @@ from django_filters import ( from core.elasticsearch import process_query from core.models import Address, Brand, Category, Feedback, Order, Product, Wishlist -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") class CaseInsensitiveListFilter(BaseInFilter, CharFilter): @@ -363,6 +363,7 @@ class CategoryFilter(FilterSet): order_by = OrderingFilter( fields=( + ("priority", "priority"), ("uuid", "uuid"), ("name", "name"), ("?", "random"), @@ -430,6 +431,7 @@ class BrandFilter(FilterSet): order_by = OrderingFilter( fields=( + ("priority", "priority"), ("uuid", "uuid"), ("name", "name"), ("?", "random"), diff --git a/core/graphene/__init__.py b/core/graphene/__init__.py index d4f3b7db..1fe565b9 100644 --- a/core/graphene/__init__.py +++ b/core/graphene/__init__.py @@ -1,10 +1,10 @@ from graphene import Mutation -class BaseMutation(Mutation): - def __init__(self, *args, **kwargs): +class BaseMutation(Mutation): # type: ignore [misc] + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) @staticmethod - def mutate(**kwargs): + def mutate(**kwargs) -> None: pass diff --git a/core/graphene/mutations.py b/core/graphene/mutations.py index 462b5cf0..1ba0445e 100644 --- a/core/graphene/mutations.py +++ b/core/graphene/mutations.py @@ -13,13 +13,14 @@ from core.elasticsearch import process_query from core.graphene import BaseMutation from core.graphene.object_types import ( AddressType, - BulkActionOrderProductInput, + BulkProductInput, OrderType, ProductType, SearchResultsType, WishlistType, + FeedbackType, ) -from core.models import Address, Category, Order, Product, Wishlist +from core.models import Address, Category, Order, Product, Wishlist, OrderProduct from core.utils import format_attributes, is_url_safe from core.utils.caching import web_cache from core.utils.emailing import contact_us_email @@ -27,7 +28,7 @@ from core.utils.messages import permission_denied_message from core.utils.nominatim import fetch_address_suggestions from payments.graphene.object_types import TransactionType -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") class CacheOperator(BaseMutation): @@ -96,8 +97,8 @@ class AddOrderProduct(BaseMutation): order = order.add_product(product_uuid=product_uuid, attributes=format_attributes(attributes)) return AddOrderProduct(order=order) - except Order.DoesNotExist: - raise Http404(_(f"order {order_uuid} not found")) + except Order.DoesNotExist as dne: + raise Http404(_(f"order {order_uuid} not found")) from dne class RemoveOrderProduct(BaseMutation): @@ -122,8 +123,8 @@ class RemoveOrderProduct(BaseMutation): order = order.remove_product(product_uuid=product_uuid, attributes=format_attributes(attributes)) return AddOrderProduct(order=order) - except Order.DoesNotExist: - raise Http404(_(f"order {order_uuid} not found")) + except Order.DoesNotExist as dne: + raise Http404(_(f"order {order_uuid} not found")) from dne class RemoveAllOrderProducts(BaseMutation): @@ -174,13 +175,14 @@ class BuyOrder(BaseMutation): description = _("buy an order") class Arguments: - order_uuid = UUID(required=False) + order_uuid = String(required=False) order_hr_id = String(required=False) force_balance = Boolean(required=False) force_payment = Boolean(required=False) - promocode_uuid = UUID(required=False) - shipping_address = UUID(required=False) - billing_address = UUID(required=False) + promocode_uuid = String(required=False) + shipping_address = String(required=False) + billing_address = String(required=False) + chosen_products = List(BulkProductInput, required=False) order = Field(OrderType, required=False) transaction = Field(TransactionType, required=False) @@ -196,6 +198,7 @@ class BuyOrder(BaseMutation): promocode_uuid=None, shipping_address=None, billing_address=None, + chosen_products=None, ): if not any([order_uuid, order_hr_id]) or all([order_uuid, order_hr_id]): raise BadRequest(_("please provide either order_uuid or order_hr_id - mutually exclusive")) @@ -214,6 +217,7 @@ class BuyOrder(BaseMutation): promocode_uuid=promocode_uuid, shipping_address=shipping_address, billing_address=billing_address, + chosen_products=chosen_products, ) match str(type(instance)): @@ -224,8 +228,8 @@ class BuyOrder(BaseMutation): case _: raise TypeError(_(f"wrong type came from order.buy() method: {type(instance)!s}")) - except Order.DoesNotExist: - raise Http404(_(f"order {order_uuid} not found")) + except Order.DoesNotExist as dne: + raise Http404(_(f"order {order_uuid} not found")) from dne class BulkOrderAction(BaseMutation): @@ -236,7 +240,7 @@ class BulkOrderAction(BaseMutation): order_uuid = UUID(required=False) order_hr_id = String(required=False) action = String(required=True, description=_("remove/add")) - products = List(BulkActionOrderProductInput, required=True) + products = List(BulkProductInput, required=True) order = Field(OrderType, required=False) @@ -271,8 +275,48 @@ class BulkOrderAction(BaseMutation): return BulkOrderAction(order=order) - except Order.DoesNotExist: - raise Http404(_(f"order {order_uuid} not found")) + except Order.DoesNotExist as dne: + raise Http404(_(f"order {order_uuid} not found")) from dne + + +class BulkWishlistAction(BaseMutation): + class Meta: + description = _("perform an action on a list of products in the wishlist") + + class Arguments: + wishlist_uuid = UUID(required=False) + action = String(required=True, description="remove/add") + products = List(BulkProductInput, required=True) + + wishlist = Field(WishlistType, required=False) + + @staticmethod + def mutate( + _parent, + info, + action, + products, + wishlist_uuid=None, + ): + if not wishlist_uuid: + raise BadRequest(_("please provide wishlist_uuid value")) + user = info.context.user + try: + wishlist = Wishlist.objects.get(user=user, uuid=wishlist_uuid) + + # noinspection PyUnreachableCode + match action: + case "add": + wishlist = wishlist.bulk_add_products(products) + case "remove": + wishlist = wishlist.bulk_remove_products(products) + case _: + raise BadRequest(_("action must be either add or remove")) + + return BulkWishlistAction(wishlist=wishlist) + + except Wishlist.DoesNotExist as dne: + raise Http404(_(f"wishlist {wishlist_uuid} not found")) from dne class BuyUnregisteredOrder(BaseMutation): @@ -344,8 +388,8 @@ class AddWishlistProduct(BaseMutation): return AddWishlistProduct(wishlist=wishlist) - except Wishlist.DoesNotExist: - raise Http404(_(f"wishlist {wishlist_uuid} not found")) + except Wishlist.DoesNotExist as dne: + raise Http404(_(f"wishlist {wishlist_uuid} not found")) from dne class RemoveWishlistProduct(BaseMutation): @@ -371,8 +415,8 @@ class RemoveWishlistProduct(BaseMutation): return RemoveWishlistProduct(wishlist=wishlist) - except Wishlist.DoesNotExist: - raise Http404(_(f"wishlist {wishlist_uuid} not found")) + except Wishlist.DoesNotExist as dne: + raise Http404(_(f"wishlist {wishlist_uuid} not found")) from dne class RemoveAllWishlistProducts(BaseMutation): @@ -398,8 +442,8 @@ class RemoveAllWishlistProducts(BaseMutation): return RemoveAllWishlistProducts(wishlist=wishlist) - except Wishlist.DoesNotExist: - raise Http404(_(f"wishlist {wishlist_uuid} not found")) + except Wishlist.DoesNotExist as dne: + raise Http404(_(f"wishlist {wishlist_uuid} not found")) from dne class BuyWishlist(BaseMutation): @@ -441,8 +485,8 @@ class BuyWishlist(BaseMutation): case _: raise TypeError(_(f"wrong type came from order.buy() method: {type(instance)!s}")) - except Wishlist.DoesNotExist: - raise Http404(_(f"wishlist {wishlist_uuid} not found")) + except Wishlist.DoesNotExist as dne: + raise Http404(_(f"wishlist {wishlist_uuid} not found")) from dne class BuyProduct(BaseMutation): @@ -483,6 +527,37 @@ class BuyProduct(BaseMutation): raise TypeError(_(f"wrong type came from order.buy() method: {type(instance)!s}")) +class FeedbackProductAction(BaseMutation): + class Meta: + description = _("add or delete a feedback for orderproduct") + + class Arguments: + order_product_uuid = UUID(required=True) + action = String(required=True, description="add/remove") + comment = String(required=False) + rating = Int(required=False) + + feedback = Field(FeedbackType, required=False) + + @staticmethod + def mutate(_parent, info, order_product_uuid, action, comment=None, rating=None): + user = info.context.user + try: + order_product = OrderProduct.objects.get(uuid=order_product_uuid) + if user != order_product.order.user or not user.has_perm("core.change_orderproduct"): + raise PermissionDenied(permission_denied_message) + match action: + case "add": + feedback = order_product.do_feedback(comment=comment, rating=rating, action="add") + case "remove": + feedback = order_product.do_feedback(action="remove") + case _: + raise BadRequest(_("action must be either `add` or `remove`")) + return FeedbackProductAction(feedback=feedback) + except OrderProduct.DoesNotExist as dne: + raise Http404(_(f"order product {order_product_uuid} not found")) from dne + + class CreateProduct(BaseMutation): class Arguments: name = String(required=True) @@ -575,9 +650,9 @@ class DeleteAddress(BaseMutation): raise PermissionDenied(permission_denied_message) - except Address.DoesNotExist: + except Address.DoesNotExist as dne: name = "Address" - raise Http404(_(f"{name} does not exist: {uuid}")) + raise Http404(_(f"{name} does not exist: {uuid}")) from dne class AutocompleteAddress(BaseMutation): diff --git a/core/graphene/object_types.py b/core/graphene/object_types.py index ef27b4b3..41d7566f 100644 --- a/core/graphene/object_types.py +++ b/core/graphene/object_types.py @@ -1,5 +1,8 @@ +import logging + +from constance import config from django.core.cache import cache -from django.db.models import Max, Min +from django.db.models import Max, Min, QuerySet from django.db.models.functions import Length from django.utils.translation import gettext_lazy as _ from graphene import ( @@ -13,6 +16,7 @@ from graphene import ( ObjectType, String, relay, + Boolean, ) from graphene.types.generic import GenericScalar from graphene_django import DjangoObjectType @@ -40,8 +44,31 @@ from core.models import ( Vendor, Wishlist, ) +from core.utils import graphene_current_lang, graphene_abs +from core.utils.seo_builders import ( + org_schema, + breadcrumb_schema, + brand_schema, + website_schema, + category_schema, + item_list_schema, + product_schema, +) +from payments.graphene.object_types import TransactionType +from payments.models import Transaction -logger = __import__("logging").getLogger(__name__) +logger = logging.getLogger("django") + + +class SEOMetaType(ObjectType): + title = String() + description = String() + canonical = String() + robots = String() + open_graph = GenericScalar() + twitter = GenericScalar() + json_ld = List(GenericScalar) + hreflang = List(GenericScalar) class AttributeType(DjangoObjectType): @@ -87,6 +114,7 @@ class AttributeGroupType(DjangoObjectType): class BrandType(DjangoObjectType): categories = List(lambda: CategoryType, description=_("categories")) + seo_meta = Field(SEOMetaType, description=_("SEO meta snapshot")) class Meta: model = Brand @@ -106,6 +134,48 @@ class BrandType(DjangoObjectType): def resolve_small_logo(self: Brand, info): return info.context.build_absolute_uri(self.small_logo.url) if self.small_logo else "" + def resolve_seo_meta(self: Brand, info): + lang = graphene_current_lang() + base = f"https://{config.BASE_DOMAIN}" + canonical = f"{base}/{lang}/brand/{self.slug}" + title = f"{self.name} | {config.PROJECT_NAME}" + description = (self.description or "")[:180] + + logo_url = None + if getattr(self, "big_logo", None): + logo_url = graphene_abs(info.context, self.big_logo.url) + elif getattr(self, "small_logo", None): + logo_url = graphene_abs(info.context, self.small_logo.url) + + og = { + "title": title, + "description": description, + "type": "website", + "url": canonical, + "image": logo_url or "", + } + tw = {"card": "summary_large_image", "title": title, "description": description, "image": logo_url or ""} + + crumbs = [("Home", f"{base}/"), (self.name, canonical)] + + json_ld = [ + org_schema(), + website_schema(), + breadcrumb_schema(crumbs), + brand_schema(self, canonical, logo_url=logo_url), + ] + + return { + "title": title, + "description": description, + "canonical": canonical, + "robots": "index,follow", + "open_graph": og, + "twitter": tw, + "json_ld": json_ld, + "hreflang": [], + } + class FilterableAttributeType(ObjectType): attribute_name = String(required=True) @@ -134,6 +204,7 @@ class CategoryType(DjangoObjectType): ) tags = DjangoFilterConnectionField(lambda: CategoryTagType, description=_("tags for this category")) products = DjangoFilterConnectionField(lambda: ProductType, description=_("products in this category")) + seo_meta = Field(SEOMetaType, description=_("SEO meta snapshot")) class Meta: model = Category @@ -216,6 +287,58 @@ class CategoryType(DjangoObjectType): "max_price": min_max_prices["max_price"], } + def resolve_seo_meta(self: Category, info): + lang = graphene_current_lang() + base = f"https://{config.BASE_DOMAIN}" + canonical = f"{base}/{lang}/catalog/{self.slug}" + title = f"{self.name} | {config.PROJECT_NAME}" + description = (self.description or "")[:180] + + og_image = graphene_abs(info.context, self.image.url) if getattr(self, "image", None) else "" + + og = { + "title": title, + "description": description, + "type": "website", + "url": canonical, + "image": og_image, + } + tw = {"card": "summary_large_image", "title": title, "description": description, "image": og_image} + + crumbs = [("Home", f"{base}/")] + for c in self.get_ancestors(): + crumbs.append((c.name, f"{base}/{lang}/catalog/{c.slug}")) + crumbs.append((self.name, canonical)) + + json_ld = [org_schema(), website_schema(), breadcrumb_schema(crumbs), category_schema(self, canonical)] + + product_urls = [] + qs = ( + Product.objects.filter( + is_active=True, + category=self, + brand__is_active=True, + stocks__vendor__is_active=True, + ) + .only("slug") + .distinct()[:24] + ) + for p in qs: + product_urls.append(f"{base}/{lang}/product/{p.slug}") + if product_urls: + json_ld.append(item_list_schema(product_urls)) + + return { + "title": title, + "description": description, + "canonical": canonical, + "robots": "index,follow", + "open_graph": og, + "twitter": tw, + "json_ld": json_ld, + "hreflang": [], + } + class VendorType(DjangoObjectType): markup_percent = Float(description=_("markup percentage")) @@ -234,6 +357,7 @@ class AddressType(DjangoObjectType): class Meta: model = Address + interfaces = (relay.Node,) fields = ( "uuid", "street", @@ -313,6 +437,7 @@ class OrderType(DjangoObjectType): is_whole_digital = Float(description=_("are all products in the order digital")) attributes = GenericScalar(description=_("attributes")) notifications = GenericScalar(description=_("notifications")) + payments_transactions = Field(TransactionType, description=_("transactions for this order")) class Meta: model = Order @@ -329,21 +454,27 @@ class OrderType(DjangoObjectType): "total_quantity", "is_whole_digital", "human_readable_id", + "payments_transactions", ) description = _("orders") - def resolve_total_price(self, _info): + def resolve_total_price(self: Order, _info): return self.total_price - def resolve_total_quantity(self, _info): + def resolve_total_quantity(self: Order, _info): return self.total_quantity - def resolve_notifications(self, _info): + def resolve_notifications(self: Order, _info): return camelize(self.notifications) - def resolve_attributes(self, _info): + def resolve_attributes(self: Order, _info): return camelize(self.attributes) + def resolve_payments_transactions(self: Order, _info) -> QuerySet[Transaction] | None: + if self.payments_transactions: + return self.payments_transactions.all() + return None + class ProductImageType(DjangoObjectType): image = String(description=_("image url")) @@ -368,6 +499,8 @@ class ProductType(DjangoObjectType): price = Float(description=_("price")) quantity = Float(description=_("quantity")) feedbacks_count = Int(description=_("number of feedbacks")) + personal_orders_only = Boolean(description=_("only available for personal orders")) + seo_meta = Field(SEOMetaType, description=_("SEO meta snapshot")) class Meta: model = Product @@ -381,13 +514,17 @@ class ProductType(DjangoObjectType): "slug", "description", "feedbacks", + "feedbacks_count", + "personal_orders_only", + "quantity", + "attribute_groups", "images", "price", ) filter_fields = ["uuid", "name"] description = _("products") - def resolve_price(self, _info) -> float: + def resolve_price(self: Product, _info) -> float: return self.price or 0.0 def resolve_feedbacks(self: Product, _info): @@ -395,7 +532,7 @@ class ProductType(DjangoObjectType): return Feedback.objects.filter(order_product__product=self) return Feedback.objects.filter(order_product__product=self, is_active=True) - def resolve_feedbacks_count(self, _info) -> int: + def resolve_feedbacks_count(self: Product, _info) -> int: return self.feedbacks_count or 0 def resolve_attribute_groups(self: Product, info): @@ -403,9 +540,58 @@ class ProductType(DjangoObjectType): return AttributeGroup.objects.filter(attributes__values__product=self).distinct() - def resolve_quantity(self, _info) -> int: + def resolve_quantity(self: Product, _info) -> int: return self.quantity or 0 + def resolve_personal_orders_only(self: Product, _info) -> bool: + return False or self.personal_orders_only + + def resolve_seo_meta(self: Product, info): + lang = graphene_current_lang() + base = f"https://{config.BASE_DOMAIN}" + canonical = f"{base}/{lang}/product/{self.slug}" + title = f"{self.name} | {config.PROJECT_NAME}" + description = (self.description or "")[:180] + + first_img = self.images.order_by("priority").first() + og_image = graphene_abs(info.context, first_img.image.url) if first_img else "" + + og = { + "title": title, + "description": description, + "type": "product", + "url": canonical, + "image": og_image, + } + tw = {"card": "summary_large_image", "title": title, "description": description, "image": og_image} + + crumbs = [("Home", f"{base}/")] + if self.category: + for c in self.category.get_ancestors(include_self=True): + crumbs.append((c.name, f"{base}/{lang}/catalog/{c.slug}")) + crumbs.append((self.name, canonical)) + + images = list(self.images.all()[:6]) + rating = {"value": self.rating, "count": self.feedbacks_count} + + json_ld = [ + org_schema(), + website_schema(), + breadcrumb_schema(crumbs), + product_schema(self, images, rating=rating), + ] + + return { + "title": title, + "description": description, + "canonical": canonical, + "robots": "index,follow", + "open_graph": og, + "twitter": tw, + "json_ld": json_ld, + "hreflang": [], + } + class AttributeValueType(DjangoObjectType): value = String(description=_("attribute value")) @@ -436,7 +622,7 @@ class PromoCodeType(DjangoObjectType): description = _("promocodes") def resolve_discount(self: PromoCode, _info) -> float: - return float(self.discount_percent) if self.discount_percent else float(self.discount_amount) + return float(self.discount_percent) if self.discount_percent else float(self.discount_amount) # type: ignore [arg-type] def resolve_discount_type(self: PromoCode, _info) -> str: return "percent" if self.discount_percent else "amount" @@ -557,6 +743,6 @@ class SearchResultsType(ObjectType): posts = List(description=_("posts search results"), of_type=SearchPostsResultsType) -class BulkActionOrderProductInput(InputObjectType): +class BulkProductInput(InputObjectType): uuid = UUID(required=True) attributes = GenericScalar(required=False) diff --git a/core/graphene/schema.py b/core/graphene/schema.py index 29ff0fd6..f7f6eab8 100644 --- a/core/graphene/schema.py +++ b/core/graphene/schema.py @@ -1,6 +1,7 @@ import logging from django.core.cache import cache +from django.utils import timezone from django.core.exceptions import PermissionDenied from graphene import Field, List, ObjectType, Schema from graphene_django.filter import DjangoFilterConnectionField @@ -14,12 +15,14 @@ from core.filters import ( OrderFilter, ProductFilter, WishlistFilter, + AddressFilter, ) from core.graphene.mutations import ( AddOrderProduct, AddWishlistProduct, AutocompleteAddress, BulkOrderAction, + BulkWishlistAction, BuyOrder, BuyProduct, BuyWishlist, @@ -29,6 +32,7 @@ from core.graphene.mutations import ( CreateProduct, DeleteAddress, DeleteProduct, + FeedbackProductAction, RemoveAllOrderProducts, RemoveAllWishlistProducts, RemoveOrderProduct, @@ -56,6 +60,7 @@ from core.graphene.object_types import ( StockType, VendorType, WishlistType, + AddressType, ) from core.models import ( AttributeGroup, @@ -73,6 +78,7 @@ from core.models import ( Stock, Vendor, Wishlist, + Address, ) from core.utils import get_project_parameters from core.utils.languages import get_flag_by_language @@ -95,7 +101,7 @@ from vibes_auth.graphene.mutations import ( from vibes_auth.graphene.object_types import UserType from vibes_auth.models import User -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") class Query(ObjectType): @@ -104,6 +110,7 @@ class Query(ObjectType): products = DjangoFilterConnectionField(ProductType, filterset_class=ProductFilter) orders = DjangoFilterConnectionField(OrderType, filterset_class=OrderFilter) users = DjangoFilterConnectionField(UserType, filterset_class=UserFilter) + addresses = DjangoFilterConnectionField(AddressType, filterset_class=AddressFilter) attribute_groups = DjangoFilterConnectionField(AttributeGroupType) categories = DjangoFilterConnectionField(CategoryType, filterset_class=CategoryFilter) vendors = DjangoFilterConnectionField(VendorType) @@ -145,7 +152,10 @@ class Query(ObjectType): Product.objects.all().select_related("brand", "category").prefetch_related("images", "stocks") if info.context.user.has_perm("core.view_product") else Product.objects.filter( - is_active=True, brand__is_active=True, category__is_active=True, stocks__isnull=False + is_active=True, + brand__is_active=True, + category__is_active=True, + stocks__vendor__is_active=True, ) .select_related("brand", "category") .prefetch_related("images", "stocks") @@ -284,7 +294,12 @@ class Query(ObjectType): promocodes = PromoCode.objects if info.context.user.has_perm("core.view_promocode"): return promocodes.filter(user__uuid=kwargs.get("user_uuid")) or promocodes.all() - return promocodes.filter(is_active=True, user=info.context.user) + return promocodes.filter( + is_active=True, + user=info.context.user, + used_on__isnull=True, + start_time__lte=timezone.now(), + ) @staticmethod def resolve_product_tags(_parent, info, **_kwargs): @@ -298,6 +313,12 @@ class Query(ObjectType): return CategoryTag.objects.all() return CategoryTag.objects.filter(is_active=True) + @staticmethod + def resolve_addresses(_parent, info, **_kwargs): + if info.context.user.has_perm("core.view_address"): + return Address.objects.all() + return Address.objects.filter(is_active=True, user=info.context.user) + class Mutation(ObjectType): search = Search.Field() @@ -314,6 +335,8 @@ class Mutation(ObjectType): remove_order_products_of_a_kind = RemoveOrderProductsOfAKind.Field() buy_order = BuyOrder.Field() bulk_order_action = BulkOrderAction.Field() + bulk_wishlist_action = BulkWishlistAction.Field() + feedback_product_action = FeedbackProductAction.Field() deposit = Deposit.Field() obtain_jwt_token = ObtainJSONWebToken.Field() refresh_jwt_token = RefreshJSONWebToken.Field() diff --git a/core/locale/ar_AR/LC_MESSAGES/django.mo b/core/locale/ar_AR/LC_MESSAGES/django.mo index 7b6f17c5..c51e2f9e 100644 Binary files a/core/locale/ar_AR/LC_MESSAGES/django.mo and b/core/locale/ar_AR/LC_MESSAGES/django.mo differ diff --git a/core/locale/ar_AR/LC_MESSAGES/django.po b/core/locale/ar_AR/LC_MESSAGES/django.po index 3438c4df..3203c1fe 100644 --- a/core/locale/ar_AR/LC_MESSAGES/django.po +++ b/core/locale/ar_AR/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,119 +13,116 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "المعرف الفريد" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "يستخدم المعرف الفريد لتحديد أي كائن قاعدة بيانات بالتأكيد" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "نشط" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" +"if set to false, this object can't be seen by users without needed permission" msgstr "" "إذا تم تعيينه على خطأ، لا يمكن للمستخدمين رؤية هذا الكائن دون الحاجة إلى إذن" -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "تم إنشاؤها" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "عندما ظهر الكائن لأول مرة في قاعدة البيانات" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "تم التعديل" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "متى تم تحرير الكائن آخر مرة" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "الترجمات" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "جنرال لواء" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "العلاقات" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "البيانات الوصفية" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "الطوابع الزمنية" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" -msgstr "تنشيط المحدد %(verbose_name_plural)s" +msgstr "تنشيط المحدد _PH_0__%(verbose_name_plural)s" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)s تم تفعيله بنجاح!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "تم تفعيل العناصر المختارة!" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" -msgstr "إلغاء تنشيط %(verbose_name_plural)s المحددة" +msgstr "إلغاء التنشيط المحدد _PH_0_%(verbose_name_plural)s" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "%(verbose_name_plural)s تم إلغاء تنشيطه بنجاح." +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "تم إلغاء تنشيط العناصر المحددة!" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "قيمة السمة" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "قيم السمات" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "الصورة" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "الصور" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "المخزون" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "الأسهم" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "طلب المنتج" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "اطلب المنتجات" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "الأطفال" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "التكوين" @@ -177,7 +174,7 @@ msgstr "مومنتال" msgid "successful" msgstr "ناجح" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "ذاكرة التخزين المؤقت للإدخال/الإخراج" @@ -187,7 +184,8 @@ msgid "" "apply key, data and timeout with authentication to write data to cache." msgstr "" "تطبيق مفتاح فقط لقراءة البيانات المسموح بها من ذاكرة التخزين المؤقت.\n" -"تطبيق مفتاح وبيانات ومهلة مع المصادقة لكتابة البيانات إلى ذاكرة التخزين المؤقت." +"تطبيق مفتاح وبيانات ومهلة مع المصادقة لكتابة البيانات إلى ذاكرة التخزين " +"المؤقت." #: core/docs/drf/views.py:32 msgid "get a list of supported languages" @@ -201,7 +199,7 @@ msgstr "الحصول على معلمات التطبيق القابلة للكش msgid "send a message to the support team" msgstr "إرسال رسالة إلى فريق الدعم" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "طلب عنوان URL مرتبط بـ CORSed. مسموح بـ https فقط." @@ -242,8 +240,7 @@ msgid "rewrite an existing attribute group saving non-editables" msgstr "إعادة كتابة مجموعة سمات موجودة تحفظ غير القابلة للتعديل" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" +msgid "rewrite some fields of an existing attribute group saving non-editables" msgstr "إعادة كتابة بعض حقول مجموعة سمات موجودة تحفظ غير القابلة للتعديل" #: core/docs/drf/viewsets.py:70 @@ -291,8 +288,7 @@ msgid "rewrite an existing attribute value saving non-editables" msgstr "إعادة كتابة قيمة سمة موجودة تحفظ غير القابلة للتعديل" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" +msgid "rewrite some fields of an existing attribute value saving non-editables" msgstr "إعادة كتابة بعض حقول قيمة سمة موجودة حفظ غير قابل للتعديل" #: core/docs/drf/viewsets.py:124 @@ -329,8 +325,8 @@ msgstr "بالنسبة للمستخدمين من غير الموظفين، يت #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" "البحث في سلسلة فرعية غير حساسة لحالة الأحرف عبر human_readable_id و " "order_products.product.name و order_products.product.partnumber" @@ -366,9 +362,9 @@ msgstr "تصفية حسب حالة الطلب (مطابقة سلسلة فرعي #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" "الترتيب حسب واحد من: uuid، معرف_بشري_مقروء، بريد_إلكتروني_مستخدم، مستخدم، " "حالة، إنشاء، تعديل، وقت_الشراء، عشوائي. البادئة بحرف \"-\" للترتيب التنازلي " @@ -411,7 +407,7 @@ msgstr "" "ينهي أمر الشراء. إذا تم استخدام \"فرض_الرصيد\"، يتم إكمال عملية الشراء " "باستخدام رصيد المستخدم؛ إذا تم استخدام \"فرض_الدفع\"، يتم بدء المعاملة." -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "شراء طلب شراء بدون إنشاء حساب" @@ -438,8 +434,7 @@ msgid "" "adds a list of products to an order using the provided `product_uuid` and " "`attributes`." msgstr "" -"يضيف قائمة من المنتجات إلى طلب باستخدام \"معرّف_المنتج\" و\"السمات\" " -"المتوفرة." +"يضيف قائمة من المنتجات إلى طلب باستخدام \"معرّف_المنتج\" و\"السمات\" المتوفرة." #: core/docs/drf/viewsets.py:266 msgid "remove product from order" @@ -449,7 +444,8 @@ msgstr "إزالة منتج من الطلب" msgid "" "removes a product from an order using the provided `product_uuid` and " "`attributes`." -msgstr "يزيل منتجًا من أحد الطلبات باستخدام \"معرّف_المنتج\" و\"السمات\" المتوفرة." +msgstr "" +"يزيل منتجًا من أحد الطلبات باستخدام \"معرّف_المنتج\" و\"السمات\" المتوفرة." #: core/docs/drf/viewsets.py:272 msgid "remove product from order, quantities will not count" @@ -535,20 +531,32 @@ msgstr "" msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "تصفية حسب زوج واحد أو أكثر من أسماء/قيم السمات. \n" "- **صيغة**: `attr_name=الطريقة-القيمة[ ؛ attr2=الطريقة2-القيمة2]...`\n" -"- **الأساليب** (افتراضيًا إلى \"يحتوي على\" إذا تم حذفها): \"بالضبط\"، \"بالضبط\"، \"بالضبط\"، \"يحتوي\"، \"يحتوي\"، \"لاغية\"، \"يبدأ ب\"، \"يبدأ ب\"، \"يبدأ ب\"، \"ينتهي ب\"، \"ينتهي ب\"، \"regex\"، \"iregex\"، \"lt\"، \"lte\"، \"gt\"، \"gte\"، \"in\n" -"- **كتابة القيمة**: تتم تجربة JSON أولًا (حتى تتمكن من تمرير القوائم/المجادلات)، \"صحيح\"/\"خطأ\" للمنطقيين والأعداد الصحيحة والعوامات؛ وإلا يتم التعامل معها كسلسلة. \n" -"- **القاعدة 64**: البادئة ب \"b64-\" لتشفير القيمة الخام بأمان لقاعدة 64- لتشفير القيمة الخام. \n" +"- **الأساليب** (افتراضيًا إلى \"يحتوي على\" إذا تم حذفها): \"بالضبط\"، " +"\"بالضبط\"، \"بالضبط\"، \"يحتوي\"، \"يحتوي\"، \"لاغية\"، \"يبدأ ب\"، \"يبدأ " +"ب\"، \"يبدأ ب\"، \"ينتهي ب\"، \"ينتهي ب\"، \"regex\"، \"iregex\"، \"lt\"، " +"\"lte\"، \"gt\"، \"gte\"، \"in\n" +"- **كتابة القيمة**: تتم تجربة JSON أولًا (حتى تتمكن من تمرير القوائم/" +"المجادلات)، \"صحيح\"/\"خطأ\" للمنطقيين والأعداد الصحيحة والعوامات؛ وإلا يتم " +"التعامل معها كسلسلة. \n" +"- **القاعدة 64**: البادئة ب \"b64-\" لتشفير القيمة الخام بأمان لقاعدة 64- " +"لتشفير القيمة الخام. \n" "أمثلة: \n" -"'color=exact-red'، 'size=gt-10'، 'features=in-[\"wifi\"،\"bluetooth\"]، 'fatures=in-[\"wifi\",\"bluetooth\"],\n" +"'color=exact-red'، 'size=gt-10'، 'features=in-[\"wifi\"،\"bluetooth\"]، " +"'fatures=in-[\"wifi\",\"bluetooth\"],\n" "\"b64-description=icontains-aGVhdC1jb2xk" #: core/docs/drf/viewsets.py:349 @@ -601,7 +609,8 @@ msgstr "(بالضبط) الرقمية مقابل المادية" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" "قائمة مفصولة بفواصل من الحقول للفرز حسب. البادئة بـ \"-\" للفرز التنازلي. \n" @@ -731,7 +740,7 @@ msgstr "حذف علاقة الطلب-المنتج" msgid "add or remove feedback on an order–product relation" msgstr "إضافة أو إزالة الملاحظات على العلاقة بين الطلب والمنتج" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "لم يتم توفير مصطلح بحث." @@ -779,8 +788,8 @@ msgstr "السمات" msgid "Quantity" msgstr "الكمية" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "سبيكة" @@ -841,214 +850,237 @@ msgstr "المستوى" msgid "Product UUID" msgstr "UUID المنتج" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "" "مفتاح للبحث عنه في ذاكرة التخزين المؤقت أو تعيينه في ذاكرة التخزين المؤقت" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "البيانات المراد تخزينها في ذاكرة التخزين المؤقت" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "المهلة بالثواني لتعيين البيانات في ذاكرة التخزين المؤقت" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "البيانات المخزنة مؤقتاً" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "بيانات JSON مجمّلة من عنوان URL المطلوب" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "يُسمح فقط بعناوين URL التي تبدأ ب http(s)://" -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "إضافة منتج إلى الطلب" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "الطلب {order_uuid} غير موجود" +msgstr "الطلب {order_uuid} غير موجود!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "إزالة منتج من الطلب" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "إزالة جميع المنتجات من الطلب" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "شراء طلبية" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "يرجى تقديم إما Order_uuid أو order_uid_hr_hr_id - متنافيان!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "جاء نوع خاطئ من طريقة order.buy(): {type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "تنفيذ إجراء على قائمة من المنتجات بالترتيب" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "إزالة/إضافة" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "يجب أن يكون الإجراء إما \"إضافة\" أو \"إزالة\"!" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "تنفيذ إجراء على قائمة المنتجات في قائمة الأمنيات" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "يُرجى تقديم قيمة \"wishlist_uid\"." + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "قائمة الرغبات {wishlist_uuid} غير موجودة!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "إضافة منتج إلى الطلب" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "قائمة الأمنيات {wishlist_uuid} غير موجودة" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "إزالة منتج من الطلب" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "إزالة منتج من الطلب" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "إزالة منتج من الطلب" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "شراء طلبية" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" msgstr "الرجاء إرسال السمات كسلسلة منسقة مثل attr1=قيمة1، attr2=قيمة2" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "إضافة أو حذف تعليق على طلبالمنتج" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "يجب أن يكون الإجراء إما \"إضافة\" أو \"إزالة\"!" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "طلب المنتج {order_product_uuid} غير موجود!" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "سلسلة العنوان الأصلي المقدمة من المستخدم" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} غير موجود: {uuid}" +msgstr "{name} غير موجود: {uuid}!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "يجب أن يكون الحد بين 1 و10" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - يعمل مثل السحر" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "السمات" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "السمات المجمعة" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "مجموعات السمات" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "الفئات" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "العلامات التجارية" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "الفئات" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "النسبة المئوية للترميز" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "ما هي السمات والقيم التي يمكن استخدامها لتصفية هذه الفئة." -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." +#: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." msgstr "" "الحد الأدنى والحد الأقصى لأسعار المنتجات في هذه الفئة، إذا كانت متوفرة." -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "العلامات الخاصة بهذه الفئة" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "المنتجات في هذه الفئة" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "البائعون" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "خط العرض (الإحداثي Y)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "خط الطول (الإحداثي X)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "كيفية" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "قيمة التصنيف من 1 إلى 10، شاملة، أو 0 إذا لم يتم تعيينها." -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "يمثل ملاحظات من المستخدم." -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "الإشعارات" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "تحميل الرابط الخاص بمنتج الطلب هذا إن أمكن" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "قائمة بطلب المنتجات بهذا الترتيب" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "عنوان إرسال الفواتير" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" @@ -1056,986 +1088,993 @@ msgstr "" "عنوان الشحن لهذا الطلب، اترك العنوان فارغًا إذا كان هو نفسه عنوان إرسال " "الفواتير أو إذا لم يكن منطبقًا" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "السعر الإجمالي لهذا الطلب" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "إجمالي كمية المنتجات بالترتيب" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "هل جميع المنتجات في الطلب رقمي" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "المعاملات الخاصة بهذا الطلب" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "الطلبات" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "رابط الصورة" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "صور المنتج" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "الفئة" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "الملاحظات" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "العلامة التجارية" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "مجموعات السمات" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "السعر" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "الكمية" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "عدد الملاحظات" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "المنتجات" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "الرموز الترويجية" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "المنتجات المعروضة للبيع" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "العروض الترويجية" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "البائع" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "المنتج" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "المنتجات المفضلة" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "قوائم التمنيات" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "المنتجات الموسومة" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "علامات المنتج" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "الفئات الموسومة" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "علامات الفئات" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "اسم المشروع" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "البريد الإلكتروني للشركة" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "اسم الشركة" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "عنوان الشركة" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "رقم هاتف الشركة" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "" -"\"البريد الإلكتروني من\"، في بعض الأحيان يجب استخدامه بدلاً من قيمة المستخدم" -" المضيف" +"\"البريد الإلكتروني من\"، في بعض الأحيان يجب استخدامه بدلاً من قيمة المستخدم " +"المضيف" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "مستخدم البريد الإلكتروني المضيف" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "الحد الأقصى لمبلغ السداد" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "الحد الأدنى لمبلغ السداد" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "بيانات التحليلات" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "بيانات الإعلانات" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "التكوين" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "رمز اللغة" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "اسم اللغة" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "علم اللغة، إذا كان موجوداً :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "الحصول على قائمة باللغات المدعومة" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "نتائج البحث عن المنتجات" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "نتائج البحث عن المنتجات" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "والد هذه المجموعة" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "مجموعة السمات الرئيسية" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "اسم مجموعة السمات" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "مجموعة السمات" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" "تخزين بيانات الاعتماد ونقاط النهاية المطلوبة لاتصالات واجهة برمجة التطبيقات " "الخاصة بالمورّد" -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "معلومات المصادقة" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "تحديد الترميز للمنتجات المسترجعة من هذا البائع" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "نسبة هامش الربح للبائع" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "اسم هذا البائع" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "اسم البائع" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "معرّف العلامة الداخلي لعلامة المنتج" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "اسم العلامة" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "اسم سهل الاستخدام لعلامة المنتج" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "اسم عرض العلامة" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "علامة المنتج" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "علامة الفئة" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "علامات الفئة" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "تحميل صورة تمثل هذه الفئة" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "صورة الفئة" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "تحديد نسبة ترميز للمنتجات في هذه الفئة" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "أصل هذه الفئة لتكوين بنية هرمية" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "الفئة الرئيسية" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "اسم الفئة" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "تقديم اسم لهذه الفئة" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "إضافة وصف تفصيلي لهذه الفئة" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "وصف الفئة" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "العلامات التي تساعد في وصف هذه الفئة أو تجميعها" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "الأولوية" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "اسم هذه العلامة التجارية" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "اسم العلامة التجارية" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "تحميل شعار يمثل هذه العلامة التجارية" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "صورة العلامة التجارية الصغيرة" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "رفع شعار كبير يمثل هذه العلامة التجارية" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "صورة كبيرة للعلامة التجارية" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "إضافة وصف تفصيلي للعلامة التجارية" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "وصف العلامة التجارية" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "الفئات الاختيارية التي ترتبط بها هذه العلامة التجارية" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "الفئات" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "الفئة التي ينتمي إليها هذا المنتج" - -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "ربط هذا المنتج اختياريًا بعلامة تجارية" - -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "العلامات التي تساعد في وصف أو تجميع هذا المنتج" - -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "يشير إلى ما إذا كان هذا المنتج يتم تسليمه رقميًا أم لا" - -#: core/models.py:351 -msgid "is product digital" -msgstr "هل المنتج رقمي" - -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "توفير اسم تعريفي واضح للمنتج" - -#: core/models.py:358 -msgid "product name" -msgstr "اسم المنتج" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "إضافة وصف تفصيلي للمنتج" - -#: core/models.py:364 -msgid "product description" -msgstr "وصف المنتج" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "رقم الجزء لهذا المنتج" - -#: core/models.py:372 -msgid "part number" -msgstr "رقم الجزء" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "فئة هذه السمة" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "مجموعة هذه السمة" - -#: core/models.py:465 -msgid "string" -msgstr "الخيط" - -#: core/models.py:466 -msgid "integer" -msgstr "عدد صحيح" - -#: core/models.py:467 -msgid "float" -msgstr "تعويم" - -#: core/models.py:468 -msgid "boolean" -msgstr "منطقية" - -#: core/models.py:469 -msgid "array" -msgstr "المصفوفة" - -#: core/models.py:470 -msgid "object" -msgstr "الكائن" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "نوع قيمة السمة" - -#: core/models.py:473 -msgid "value type" -msgstr "نوع القيمة" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "اسم هذه السمة" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "اسم السمة" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "السمة" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "سمة هذه القيمة" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "المنتج المحدد المرتبط بقيمة هذه السمة" - -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 -msgid "associated product" -msgstr "المنتج المرتبط" - -#: core/models.py:512 -msgid "the specific value for this attribute" -msgstr "القيمة المحددة لهذه السمة" - -#: core/models.py:528 -msgid "provide alternative text for the image for accessibility" -msgstr "توفير نص بديل للصورة لإمكانية الوصول" - -#: core/models.py:529 -msgid "image alt text" -msgstr "النص البديل للصورة" - -#: core/models.py:532 -msgid "upload the image file for this product" -msgstr "تحميل ملف الصورة لهذا المنتج" - -#: core/models.py:533 core/models.py:558 -msgid "product image" -msgstr "صورة المنتج" - -#: core/models.py:539 -msgid "determines the order in which images are displayed" -msgstr "يحدد الترتيب الذي يتم عرض الصور به" - -#: core/models.py:540 -msgid "display priority" -msgstr "أولوية العرض" - -#: core/models.py:545 -msgid "the product that this image represents" -msgstr "المنتج الذي تمثله هذه الصورة" - -#: core/models.py:559 -msgid "product images" -msgstr "صور المنتج" - -#: core/models.py:567 -msgid "percentage discount for the selected products" -msgstr "النسبة المئوية للخصم على المنتجات المختارة" - -#: core/models.py:568 -msgid "discount percentage" -msgstr "نسبة الخصم" - -#: core/models.py:573 -msgid "provide a unique name for this promotion" -msgstr "تقديم اسم فريد لهذا العرض الترويجي" - -#: core/models.py:574 -msgid "promotion name" -msgstr "اسم الترقية" - -#: core/models.py:580 -msgid "promotion description" -msgstr "وصف الترقية" - -#: core/models.py:585 -msgid "select which products are included in this promotion" -msgstr "حدد المنتجات المشمولة في هذا العرض الترويجي" - -#: core/models.py:586 -msgid "included products" -msgstr "المنتجات المشمولة" - -#: core/models.py:590 -msgid "promotion" -msgstr "الترقية" - -#: core/models.py:605 +#: core/models.py:515 msgid "the vendor supplying this product stock" msgstr "البائع الذي يورد هذا المنتج المخزون" -#: core/models.py:606 +#: core/models.py:516 msgid "associated vendor" msgstr "البائع المرتبط" -#: core/models.py:610 +#: core/models.py:520 msgid "final price to the customer after markups" msgstr "السعر النهائي للعميل بعد هوامش الربح" -#: core/models.py:611 +#: core/models.py:521 msgid "selling price" msgstr "سعر البيع" -#: core/models.py:616 +#: core/models.py:526 msgid "the product associated with this stock entry" msgstr "المنتج المرتبط بإدخال المخزون هذا" -#: core/models.py:624 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "المنتج المرتبط" + +#: core/models.py:534 msgid "the price paid to the vendor for this product" msgstr "السعر المدفوع للبائع مقابل هذا المنتج" -#: core/models.py:625 +#: core/models.py:535 msgid "vendor purchase price" msgstr "سعر الشراء من البائع" -#: core/models.py:629 +#: core/models.py:539 msgid "available quantity of the product in stock" msgstr "الكمية المتوفرة من المنتج في المخزون" -#: core/models.py:630 +#: core/models.py:540 msgid "quantity in stock" msgstr "الكمية في المخزون" -#: core/models.py:634 +#: core/models.py:544 msgid "vendor-assigned SKU for identifying the product" msgstr "SKU المعين من قبل البائع لتحديد المنتج" -#: core/models.py:635 +#: core/models.py:545 msgid "vendor sku" msgstr "وحدة تخزين البائع" -#: core/models.py:641 +#: core/models.py:551 msgid "digital file associated with this stock if applicable" msgstr "الملف الرقمي المرتبط بهذا المخزون إن أمكن" -#: core/models.py:642 +#: core/models.py:552 msgid "digital file" msgstr "ملف رقمي" -#: core/models.py:651 +#: core/models.py:561 msgid "stock entries" msgstr "إدخالات المخزون" -#: core/models.py:660 +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "الفئة التي ينتمي إليها هذا المنتج" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "ربط هذا المنتج اختياريًا بعلامة تجارية" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "العلامات التي تساعد في وصف أو تجميع هذا المنتج" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "يشير إلى ما إذا كان هذا المنتج يتم تسليمه رقميًا أم لا" + +#: core/models.py:626 +msgid "is product digital" +msgstr "هل المنتج رقمي" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "توفير اسم تعريفي واضح للمنتج" + +#: core/models.py:633 +msgid "product name" +msgstr "اسم المنتج" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "إضافة وصف تفصيلي للمنتج" + +#: core/models.py:639 +msgid "product description" +msgstr "وصف المنتج" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "رقم الجزء لهذا المنتج" + +#: core/models.py:647 +msgid "part number" +msgstr "رقم الجزء" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "فئة هذه السمة" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "مجموعة هذه السمة" + +#: core/models.py:767 +msgid "string" +msgstr "الخيط" + +#: core/models.py:768 +msgid "integer" +msgstr "عدد صحيح" + +#: core/models.py:769 +msgid "float" +msgstr "تعويم" + +#: core/models.py:770 +msgid "boolean" +msgstr "منطقية" + +#: core/models.py:771 +msgid "array" +msgstr "المصفوفة" + +#: core/models.py:772 +msgid "object" +msgstr "الكائن" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "نوع قيمة السمة" + +#: core/models.py:775 +msgid "value type" +msgstr "نوع القيمة" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "اسم هذه السمة" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "اسم السمة" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "السمة" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "سمة هذه القيمة" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "المنتج المحدد المرتبط بقيمة هذه السمة" + +#: core/models.py:837 +msgid "the specific value for this attribute" +msgstr "القيمة المحددة لهذه السمة" + +#: core/models.py:871 +msgid "provide alternative text for the image for accessibility" +msgstr "توفير نص بديل للصورة لإمكانية الوصول" + +#: core/models.py:872 +msgid "image alt text" +msgstr "النص البديل للصورة" + +#: core/models.py:875 +msgid "upload the image file for this product" +msgstr "تحميل ملف الصورة لهذا المنتج" + +#: core/models.py:876 core/models.py:901 +msgid "product image" +msgstr "صورة المنتج" + +#: core/models.py:882 +msgid "determines the order in which images are displayed" +msgstr "يحدد الترتيب الذي يتم عرض الصور به" + +#: core/models.py:883 +msgid "display priority" +msgstr "أولوية العرض" + +#: core/models.py:888 +msgid "the product that this image represents" +msgstr "المنتج الذي تمثله هذه الصورة" + +#: core/models.py:902 +msgid "product images" +msgstr "صور المنتج" + +#: core/models.py:943 +msgid "percentage discount for the selected products" +msgstr "النسبة المئوية للخصم على المنتجات المختارة" + +#: core/models.py:944 +msgid "discount percentage" +msgstr "نسبة الخصم" + +#: core/models.py:949 +msgid "provide a unique name for this promotion" +msgstr "تقديم اسم فريد لهذا العرض الترويجي" + +#: core/models.py:950 +msgid "promotion name" +msgstr "اسم الترقية" + +#: core/models.py:956 +msgid "promotion description" +msgstr "وصف الترقية" + +#: core/models.py:961 +msgid "select which products are included in this promotion" +msgstr "حدد المنتجات المشمولة في هذا العرض الترويجي" + +#: core/models.py:962 +msgid "included products" +msgstr "المنتجات المشمولة" + +#: core/models.py:966 +msgid "promotion" +msgstr "الترقية" + +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "المنتجات التي حددها المستخدم على أنها مطلوبة" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "المستخدم الذي يمتلك قائمة الرغبات هذه" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "مالك قائمة الرغبات" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "قائمة الرغبات" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} غير موجود: {product_uuid}" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "فيلم وثائقي" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "الأفلام الوثائقية" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "لم يتم حلها" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "سطر العنوان للعميل" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "سطر العنوان" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "الشارع" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "المنطقة" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "المدينة" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "المنطقة" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "الرمز البريدي" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "البلد" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "نقطة تحديد الموقع الجغرافي(خط الطول، خط العرض)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "استجابة JSON كاملة من أداة التشفير الجغرافي لهذا العنوان" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "استجابة JSON مخزّنة من خدمة الترميز الجغرافي" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "العنوان" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "العناوين" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "الرمز الفريد الذي يستخدمه المستخدم لاسترداد قيمة الخصم" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "معرّف الرمز الترويجي" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "مبلغ الخصم الثابت المطبق في حالة عدم استخدام النسبة المئوية" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "مبلغ الخصم الثابت" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "النسبة المئوية للخصم المطبق في حالة عدم استخدام مبلغ ثابت" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "النسبة المئوية للخصم" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "الطابع الزمني عند انتهاء صلاحية الرمز الترويجي" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "وقت انتهاء الصلاحية" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "الطابع الزمني الذي يكون هذا الرمز الترويجي صالحاً منه" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "وقت بدء الصلاحية" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" -msgstr "" -"الطابع الزمني عند استخدام الرمز الترويجي، فارغ إذا لم يتم استخدامه بعد" +msgstr "الطابع الزمني عند استخدام الرمز الترويجي، فارغ إذا لم يتم استخدامه بعد" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "الطابع الزمني للاستخدام" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "المستخدم المعين لهذا الرمز الترويجي إن أمكن" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "المستخدم المعين" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "الرمز الترويجي" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "الرموز الترويجية" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." msgstr "" -"يجب تحديد نوع واحد فقط من الخصم (المبلغ أو النسبة المئوية)، وليس كلا النوعين" -" أو لا هذا ولا ذاك." +"يجب تحديد نوع واحد فقط من الخصم (المبلغ أو النسبة المئوية)، وليس كلا النوعين " +"أو لا هذا ولا ذاك." -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "تم استخدام الرمز الترويجي بالفعل" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" msgstr "نوع الخصم غير صالح للرمز الترويجي {self.uuid}" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "عنوان إرسال الفواتير المستخدم لهذا الطلب" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "الرمز الترويجي الاختياري المطبق على هذا الطلب" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "الرمز الترويجي المطبق" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "عنوان الشحن المستخدم لهذا الطلب" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "عنوان الشحن" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "الحالة الحالية للطلب في دورة حياته" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "حالة الطلب" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" "بنية JSON للإشعارات التي سيتم عرضها للمستخدمين، في واجهة مستخدم المشرف، يتم " "استخدام عرض الجدول" -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "تمثيل JSON لسمات الطلب لهذا الطلب" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "المستخدم الذي قدم الطلب" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "المستخدم" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "الطابع الزمني عند الانتهاء من الطلب" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "وقت الشراء" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "معرّف يمكن قراءته بواسطة البشر للطلب" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "معرّف يمكن قراءته من قبل البشر" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "الطلب" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "يجب أن يكون لدى المستخدم طلب واحد فقط معلق في كل مرة!" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "لا يمكنك إضافة منتجات إلى طلب غير معلق إلى طلب غير معلق" -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "لا يمكنك إضافة منتجات غير نشطة للطلب" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "لا يمكنك إضافة منتجات أكثر من المتوفرة في المخزون" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "لا يمكنك إزالة المنتجات من طلب غير معلق من طلب غير معلق" -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "{name} غير موجود مع الاستعلام <{query}>" +msgstr "{name} غير موجود مع الاستعلام <{query}>!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "الرمز الترويجي غير موجود" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "يمكنك فقط شراء المنتجات المادية مع تحديد عنوان الشحن فقط!" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "العنوان غير موجود" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "لا يمكنك الشراء في هذه اللحظة، يرجى المحاولة مرة أخرى بعد بضع دقائق." -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "قيمة القوة غير صالحة" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "لا يمكنك شراء طلبية فارغة!" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "لا يمكنك شراء طلب بدون مستخدم!" + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "المستخدم بدون رصيد لا يمكنه الشراء بالرصيد!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "عدم كفاية الأموال لإكمال الطلب" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" msgstr "" -"لا يمكنك الشراء بدون تسجيل، يرجى تقديم المعلومات التالية: اسم العميل، البريد" -" الإلكتروني للعميل، رقم هاتف العميل" +"لا يمكنك الشراء بدون تسجيل، يرجى تقديم المعلومات التالية: اسم العميل، البريد " +"الإلكتروني للعميل، رقم هاتف العميل" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" msgstr "" "طريقة الدفع غير صالحة: {payment_method} من {available_payment_methods}!" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "السعر الذي دفعه العميل لهذا المنتج وقت الشراء" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "سعر الشراء وقت الطلب" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "تعليقات داخلية للمسؤولين حول هذا المنتج المطلوب" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "التعليقات الداخلية" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "إشعارات المستخدم" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "تمثيل JSON لسمات هذا العنصر" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "سمات المنتج المطلوبة" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "الإشارة إلى الطلب الأصلي الذي يحتوي على هذا المنتج" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "ترتيب الوالدين" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "المنتج المحدد المرتبط بخط الطلب هذا" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "كمية هذا المنتج المحدد في الطلب" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "كمية المنتج" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "الحالة الحالية لهذا المنتج بالترتيب" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "حالة خط الإنتاج" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "يجب أن يكون لـ Orderproduct طلب مرتبط به!" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "إجراء خاطئ محدد للتغذية الراجعة: {action}" +msgstr "تم تحديد إجراء خاطئ للتغذية الراجعة: {action}!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "لا يمكنك التعليق على طلب لم يتم استلامه" -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "تنزيل" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "التنزيلات" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "لا يمكنك تنزيل أصل رقمي لطلب غير مكتمل" -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "التعليقات المقدمة من المستخدمين حول تجربتهم مع المنتج" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "تعليقات على الملاحظات" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "الإشارة إلى المنتج المحدد في الطلب الذي تدور حوله هذه الملاحظات" -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "منتجات الطلبات ذات الصلة" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "التصنيف المعين من قبل المستخدم للمنتج" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "تصنيف المنتج" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "الملاحظات" @@ -2044,13 +2083,13 @@ msgid "" "you must provide a comment, rating, and order product uuid to add feedback." msgstr "يجب عليك تقديم تعليق، وتقييم، وطلب المنتج uuid لإضافة ملاحظاتك." -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "خطأ أثناء إنشاء الرمز الترويجي: {e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2059,7 +2098,7 @@ msgid "order confirmation" msgstr "تأكيد الطلب" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2070,27 +2109,28 @@ msgstr "الشعار" #: core/templates/shipped_order_delivered_email.html:100 #, python-format msgid "hello %(order.user.first_name)s," -msgstr "مرحبًا %(order.user.first_name)s," +msgstr "مرحباً %(order.user.first_name)s," #: core/templates/digital_order_created_email.html:102 #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" msgstr "" -"شكرًا لك على طلبك #%(order.pk)s! يسعدنا إبلاغك بأننا قد أخذنا طلبك في العمل." -" فيما يلي تفاصيل طلبك:" +"شكرًا لك على طلبك #%(order.pk)s! يسعدنا إبلاغك بأننا قد أخذنا طلبك في العمل. " +"فيما يلي تفاصيل طلبك:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "الإجمالي" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2110,30 +2150,30 @@ msgstr "" #: core/templates/digital_order_created_email.html:133 #, python-format msgid "best regards,
the %(config.PROJECT_NAME)s team" -msgstr "مع أطيب التحيات، فريق عمل %(config.PROJECT_NAME)s" +msgstr "مع أطيب تحياتي،
فريق %(config.PROJECT_NAME)s" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "جميع الحقوق محفوظة" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "تم تسليم الطلب" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "مرحباً %(user_first_name)s," -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" " details of your order:" -msgstr "لقد قمنا بمعالجة طلبك بنجاح №%(order_uuid)s__! فيما يلي تفاصيل طلبك:" +msgstr "لقد قمنا بمعالجة طلبك بنجاح №%(order_uuid)s! فيما يلي تفاصيل طلبك:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2141,12 +2181,12 @@ msgstr "" "معلومات إضافية\n" " معلومات إضافية" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "القيمة" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -2154,10 +2194,10 @@ msgid "" msgstr "" "إذا كانت لديك أي أسئلة، فلا تتردد في الاتصال بدعمنا على %(contact_email)s." -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "مع أطيب التحيات، فريق عمل %(project_name)s" +msgstr "مع أطيب تحياتي،
فريق %(project_name)s" #: core/templates/json_table_widget.html:5 msgid "key" @@ -2166,7 +2206,8 @@ msgstr "المفتاح" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" msgstr "شكرًا لك على طلبك! يسعدنا تأكيد طلبك. فيما يلي تفاصيل طلبك:" @@ -2184,7 +2225,7 @@ msgstr "سيتم توصيل طلبك إلى العنوان التالي:" #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "مع أطيب تحياتي،
فريق عمل %(config.PROJECT_NAME)s" +msgstr "مع أطيب تحياتي،
فريق %(config.PROJECT_NAME)s" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2203,30 +2244,20 @@ msgstr "كل من البيانات والمهلة مطلوبة" msgid "invalid timeout value, it must be between 0 and 216000 seconds" msgstr "قيمة المهلة غير صالحة، يجب أن تكون بين 0 و216000 ثانية" -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "يجب أن يكون {model} نموذجًا" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "يجب أن تكون {data} كائن قائمة" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | بدء الاتصال بنا" +msgstr "{config.PROJECT_NAME} | بادر بالاتصال بنا" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" msgstr "{config.PROJECT_NAME} | تأكيد الطلب" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" -msgstr "{config.PROJECT_NAME} | تم تسليم الطلب" +msgstr "{config.PROJECT_NAME} | طلبية تم تسليمها" #: core/utils/messages.py:3 msgid "you do not have permission to perform this action." @@ -2239,21 +2270,21 @@ msgstr "يجب تكوين معلمة NOMINATIM_URL!" #: core/validators.py:16 #, python-brace-format msgid "image dimensions should not exceed w{max_width} x h{max_height} pixels" -msgstr "يجب ألا تتجاوز أبعاد الصورة w{max_width} x h{max_height} بكسل" +msgstr "يجب ألا تتجاوز أبعاد الصورة w{max_width} x h{max_height} بكسل!" #: core/validators.py:22 msgid "invalid phone number format" msgstr "تنسيق رقم الهاتف غير صالح" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "يمكنك تنزيل الأصل الرقمي مرة واحدة فقط" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "الرمز المفضل غير موجود" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "خطأ في الترميز الجغرافي: {e}" diff --git a/core/locale/cs_CZ/LC_MESSAGES/django.mo b/core/locale/cs_CZ/LC_MESSAGES/django.mo index a6208ad4..7afca15f 100644 Binary files a/core/locale/cs_CZ/LC_MESSAGES/django.mo and b/core/locale/cs_CZ/LC_MESSAGES/django.mo differ diff --git a/core/locale/cs_CZ/LC_MESSAGES/django.po b/core/locale/cs_CZ/LC_MESSAGES/django.po index ae574cb7..1712b0dd 100644 --- a/core/locale/cs_CZ/LC_MESSAGES/django.po +++ b/core/locale/cs_CZ/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,121 +13,118 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "Jedinečné ID" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "" "Jedinečné ID slouží k jisté identifikaci jakéhokoli databázového objektu." -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "Je aktivní" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" +"if set to false, this object can't be seen by users without needed permission" msgstr "" "Pokud je nastaveno na false, nemohou tento objekt vidět uživatelé bez " "potřebného oprávnění." -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "Vytvořeno" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "Kdy se objekt poprvé objevil v databázi" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "Upraveno" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "Kdy byl objekt naposledy upraven" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "Překlady" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "Obecné" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "Vztahy" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "Metadata" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "Časová razítka" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" -msgstr "Aktivovat vybrané %(verbose_name_plural)s" +msgstr "Aktivace vybraného %(verbose_name_plural)s" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)s úspěšně aktivován!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "Vybrané položky byly aktivovány!" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" -msgstr "Deaktivovat vybrané %(verbose_name_plural)s" +msgstr "Deaktivace vybraných %(verbose_name_plural)s" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "%(verbose_name_plural)s byl úspěšně deaktivován." +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "Vybrané položky byly deaktivovány!" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "Hodnota atributu" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "Hodnoty atributů" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "Obrázek" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "Obrázky" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "Stock" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "Zásoby" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "Objednat produkt" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "Objednat produkty" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "Děti" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "Konfigurace" @@ -179,7 +176,7 @@ msgstr "Momental" msgid "successful" msgstr "Úspěšné" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "Vstup/výstup mezipaměti" @@ -203,7 +200,7 @@ msgstr "Získání vystavitelných parametrů aplikace" msgid "send a message to the support team" msgstr "Odeslání zprávy týmu podpory" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "Vyžádejte si adresu URL s protokolem CORS. Povoleno pouze https." @@ -246,8 +243,7 @@ msgstr "" "Přepsání existující skupiny atributů s uložením neupravitelných položek" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" +msgid "rewrite some fields of an existing attribute group saving non-editables" msgstr "" "Přepsání některých polí existující skupiny atributů s uložením " "neupravitelných položek" @@ -299,8 +295,7 @@ msgid "rewrite an existing attribute value saving non-editables" msgstr "Přepsání existující hodnoty atributu uložením neupravitelných položek" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" +msgid "rewrite some fields of an existing attribute value saving non-editables" msgstr "" "Přepsání některých polí existující hodnoty atributu s uložením " "neupravitelných položek" @@ -342,12 +337,12 @@ msgstr "" #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" "Vyhledávání podřetězců bez ohledu na velikost písmen v položkách " -"human_readable_id, order_products.product.name a " -"order_products.product.partnumber" +"human_readable_id, order_products.product.name a order_products.product." +"partnumber" #: core/docs/drf/viewsets.py:165 msgid "Filter orders with buy_time >= this ISO 8601 datetime" @@ -383,9 +378,9 @@ msgstr "" #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" "Řazení podle jedné z následujících možností: uuid, human_readable_id, " "user_email, user, status, created, modified, buy_time, random. Pro sestupné " @@ -426,11 +421,11 @@ msgid "" "completed using the user's balance; if `force_payment` is used, a " "transaction is initiated." msgstr "" -"Dokončí nákup objednávky. Pokud je použito `force_balance`, nákup se dokončí" -" s použitím zůstatku uživatele; pokud je použito `force_payment`, zahájí se " +"Dokončí nákup objednávky. Pokud je použito `force_balance`, nákup se dokončí " +"s použitím zůstatku uživatele; pokud je použito `force_payment`, zahájí se " "transakce." -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "zakoupení objednávky bez vytvoření účtu" @@ -542,8 +537,7 @@ msgstr "Přidání mnoha produktů do seznamu přání" #: core/docs/drf/viewsets.py:320 msgid "adds many products to an wishlist using the provided `product_uuids`" -msgstr "" -"Přidá mnoho produktů do seznamu přání pomocí zadaných `product_uuids`." +msgstr "Přidá mnoho produktů do seznamu přání pomocí zadaných `product_uuids`." #: core/docs/drf/viewsets.py:325 msgid "remove many products from wishlist" @@ -559,18 +553,28 @@ msgstr "" msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "Filtrování podle jedné nebo více dvojic název/hodnota atributu. \n" "- **Syntaxe**: `attr_name=method-value[;attr2=method2-value2]...`\n" -"- **Metody** (pokud je vynecháno, výchozí hodnota je `obsahuje`): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`\n" -"- **Typování hodnot**: Pro booleany, celá čísla, floaty se nejprve zkouší JSON (takže můžete předávat seznamy/dicty), `true`/`false`; jinak se s nimi zachází jako s řetězci. \n" -"- **Base64**: předpona `b64-` pro bezpečné zakódování surové hodnoty do URL base64. \n" +"- **Metody** (pokud je vynecháno, výchozí hodnota je `obsahuje`): `iexact`, " +"`exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, " +"`endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`\n" +"- **Typování hodnot**: Pro booleany, celá čísla, floaty se nejprve zkouší " +"JSON (takže můžete předávat seznamy/dicty), `true`/`false`; jinak se s nimi " +"zachází jako s řetězci. \n" +"- **Base64**: předpona `b64-` pro bezpečné zakódování surové hodnoty do URL " +"base64. \n" "Příklady: \n" "`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\", \"bluetooth\"]`,\n" "`b64-description=icontains-aGVhdC1jb2xk`" @@ -625,10 +629,12 @@ msgstr "(přesně) Digitální vs. fyzické" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" -"Seznam polí oddělených čárkou, podle kterých se má třídit. Pro sestupné řazení použijte předponu `-`. \n" +"Seznam polí oddělených čárkou, podle kterých se má třídit. Pro sestupné " +"řazení použijte předponu `-`. \n" "**Povolené:** uuid, rating, name, slug, created, modified, price, random" #: core/docs/drf/viewsets.py:441 @@ -756,7 +762,7 @@ msgstr "odstranit vztah objednávka-produkt" msgid "add or remove feedback on an order–product relation" msgstr "přidat nebo odebrat zpětnou vazbu na vztah objednávka-produkt." -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "Nebyl zadán žádný vyhledávací termín." @@ -804,8 +810,8 @@ msgstr "Atributy" msgid "Quantity" msgstr "Množství" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "Slug" @@ -867,216 +873,238 @@ msgstr "Úroveň" msgid "Product UUID" msgstr "UUID produktu" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "Klíč k vyhledání v keši nebo nastavení do keše" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "Data k uložení do mezipaměti" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "Časový limit v sekundách pro nastavení dat do mezipaměti" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "Data uložená v mezipaměti" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "Kamelizovaná data JSON z požadované adresy URL" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "Povoleny jsou pouze adresy URL začínající http(s)://." -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "Přidání produktu do objednávky" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "Objednávka {order_uuid} nebyla nalezena" +msgstr "Objednávka {order_uuid} nebyla nalezena!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "Odstranění produktu z objednávky" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "Odstranění všech produktů z objednávky" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "Koupit objednávku" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "Zadejte prosím order_uuid nebo order_hr_id - vzájemně se vylučují!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "Z metody order.buy() pochází nesprávný typ: {type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "Provedení akce na seznamu produktů v objednávce" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "Odebrat/přidat" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "Akce musí být buď \"přidat\", nebo \"odebrat\"!" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "Provedení akce na seznamu produktů v seznamu přání" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "Zadejte prosím hodnotu `wishlist_uuid`." + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "Seznam přání {wishlist_uuid} nenalezen!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "Přidání produktu do objednávky" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "Seznam přání {wishlist_uuid} nebyl nalezen" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "Odstranění produktu z objednávky" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "Odstranění produktu z objednávky" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "Odstranění produktu z objednávky" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "Koupit objednávku" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" msgstr "" -"Prosím, pošlete atributy jako řetězec ve formátu " -"attr1=hodnota1,attr2=hodnota2." +"Prosím, pošlete atributy jako řetězec ve formátu attr1=hodnota1," +"attr2=hodnota2." -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "Přidání nebo odstranění zpětné vazby pro objednávkuprodukt" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "Akce musí být buď `add` nebo `remove`!" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "Orderproduct {order_product_uuid} nenalezen!" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "Původní řetězec adresy zadaný uživatelem" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} neexistuje: {uuid}" +msgstr "{name} neexistuje: {uuid}!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "Limit musí být mezi 1 a 10" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - funguje jako kouzlo" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "Atributy" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "Seskupené atributy" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "Skupiny atributů" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "Kategorie" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "Značky" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "Kategorie" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "Procento přirážky" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "Které atributy a hodnoty lze použít pro filtrování této kategorie." -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." -msgstr "" -"Minimální a maximální ceny produktů v této kategorii, pokud jsou k " -"dispozici." - #: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." +msgstr "" +"Minimální a maximální ceny produktů v této kategorii, pokud jsou k dispozici." + +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "Štítky pro tuto kategorii" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "Produkty v této kategorii" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "Prodejci" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "Zeměpisná šířka (souřadnice Y)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "Zeměpisná délka (souřadnice X)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "Jak na to" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "Hodnota hodnocení od 1 do 10 včetně nebo 0, pokud není nastaveno." -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "Představuje zpětnou vazbu od uživatele." -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "Oznámení" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "Stáhněte si url adresu pro tento objednaný produkt, pokud je to možné" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "Seznam objednaných produktů v tomto pořadí" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "Fakturační adresa" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" @@ -1084,731 +1112,728 @@ msgstr "" "Dodací adresa pro tuto objednávku, pokud je stejná jako fakturační adresa " "nebo pokud není použitelná, ponechte prázdné." -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "Celková cena této objednávky" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "Celkové množství objednaných produktů" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "Jsou všechny produkty v objednávce digitální" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "Transakce pro tuto objednávku" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "Objednávky" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "Adresa URL obrázku" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "Obrázky produktu" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "Kategorie" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "Zpětná vazba" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "Značka" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "Skupiny atributů" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "Cena" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "Množství" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "Počet zpětných vazeb" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "Produkty" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "Propagační kódy" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "Produkty v prodeji" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "Propagační akce" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "Prodejce" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "Produkt" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "Produkty uvedené na seznamu přání" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "Seznamy přání" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "Produkty s příznakem" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "Štítky produktu" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "Kategorie s příznakem" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "Štítky kategorií" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "Název projektu" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "E-mail společnosti" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "Název společnosti" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "Adresa společnosti" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "Telefonní číslo společnosti" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "" "'email from', někdy se musí použít místo hodnoty hostitelského uživatele." -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "Uživatel hostitelského e-mailu" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "Maximální částka pro platbu" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "Minimální částka pro platbu" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "Analytická data" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "Reklamní údaje" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "Konfigurace" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "Kód jazyka" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "Název jazyka" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "Příznak jazyka, pokud existuje :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "Získat seznam podporovaných jazyků" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "Výsledky vyhledávání produktů" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "Výsledky vyhledávání produktů" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "Rodič této skupiny" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "Nadřazená skupina atributů" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "Název skupiny atributů" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "Skupina atributů" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" "Ukládá pověření a koncové body potřebné pro komunikaci s rozhraním API " "dodavatele." -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "Informace o ověřování" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "Definice přirážky pro produkty získané od tohoto dodavatele" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "Procento přirážky prodejce" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "Název tohoto prodejce" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "Název prodejce" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "Interní identifikátor značky produktu" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "Název štítku" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "Uživatelsky přívětivý název pro značku produktu" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "Zobrazení názvu štítku" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "Štítek produktu" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "značka kategorie" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "štítky kategorií" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "Nahrát obrázek reprezentující tuto kategorii" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "Obrázek kategorie" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "Definovat procento přirážky pro produkty v této kategorii." -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "Nadřízený této kategorie, který tvoří hierarchickou strukturu." -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "Nadřazená kategorie" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "Název kategorie" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "Uveďte název této kategorie" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "Přidejte podrobný popis této kategorie" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "Popis kategorie" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "značky, které pomáhají popsat nebo seskupit tuto kategorii" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "Priorita" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "Název této značky" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "Název značky" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "Nahrát logo reprezentující tuto značku" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "Malý obrázek značky" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "Nahrát velké logo reprezentující tuto značku" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "Velká image značky" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "Přidejte podrobný popis značky" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "Popis značky" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "Volitelné kategorie, se kterými je tato značka spojena" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "Kategorie" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "Kategorie, do které tento produkt patří" - -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "Volitelně přiřadit tento produkt ke značce" - -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "Značky, které pomáhají popsat nebo seskupit tento produkt" - -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "Označuje, zda je tento produkt dodáván digitálně" - -#: core/models.py:351 -msgid "is product digital" -msgstr "Je produkt digitální" - -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "Uveďte jasný identifikační název výrobku" - -#: core/models.py:358 -msgid "product name" -msgstr "Název produktu" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "Přidejte podrobný popis produktu" - -#: core/models.py:364 -msgid "product description" -msgstr "Popis produktu" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "Číslo dílu pro tento produkt" - -#: core/models.py:372 -msgid "part number" -msgstr "Číslo dílu" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "Kategorie tohoto atributu" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "Skupina tohoto atributu" - -#: core/models.py:465 -msgid "string" -msgstr "Řetězec" - -#: core/models.py:466 -msgid "integer" -msgstr "Celé číslo" - -#: core/models.py:467 -msgid "float" -msgstr "Float" - -#: core/models.py:468 -msgid "boolean" -msgstr "Boolean" - -#: core/models.py:469 -msgid "array" -msgstr "Pole" - -#: core/models.py:470 -msgid "object" -msgstr "Objekt" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "Typ hodnoty atributu" - -#: core/models.py:473 -msgid "value type" -msgstr "Typ hodnoty" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "Název tohoto atributu" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "Název atributu" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "Atribut" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "Atribut této hodnoty" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "Konkrétní produkt spojený s hodnotou tohoto atributu" - -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 -msgid "associated product" -msgstr "Související produkt" - -#: core/models.py:512 -msgid "the specific value for this attribute" -msgstr "Konkrétní hodnota tohoto atributu" - -#: core/models.py:528 -msgid "provide alternative text for the image for accessibility" -msgstr "Poskytněte alternativní text k obrázku kvůli přístupnosti." - -#: core/models.py:529 -msgid "image alt text" -msgstr "Text alt obrázku" - -#: core/models.py:532 -msgid "upload the image file for this product" -msgstr "Nahrát soubor s obrázkem tohoto produktu" - -#: core/models.py:533 core/models.py:558 -msgid "product image" -msgstr "Obrázek produktu" - -#: core/models.py:539 -msgid "determines the order in which images are displayed" -msgstr "Určuje pořadí, v jakém se obrázky zobrazují." - -#: core/models.py:540 -msgid "display priority" -msgstr "Priorita zobrazení" - -#: core/models.py:545 -msgid "the product that this image represents" -msgstr "Výrobek, který tento obrázek představuje" - -#: core/models.py:559 -msgid "product images" -msgstr "Obrázky produktů" - -#: core/models.py:567 -msgid "percentage discount for the selected products" -msgstr "Procentuální sleva na vybrané produkty" - -#: core/models.py:568 -msgid "discount percentage" -msgstr "Procento slevy" - -#: core/models.py:573 -msgid "provide a unique name for this promotion" -msgstr "Uveďte jedinečný název této propagační akce" - -#: core/models.py:574 -msgid "promotion name" -msgstr "Název akce" - -#: core/models.py:580 -msgid "promotion description" -msgstr "Popis propagace" - -#: core/models.py:585 -msgid "select which products are included in this promotion" -msgstr "Vyberte, které produkty jsou zahrnuty do této akce" - -#: core/models.py:586 -msgid "included products" -msgstr "Zahrnuté produkty" - -#: core/models.py:590 -msgid "promotion" -msgstr "Propagace" - -#: core/models.py:605 +#: core/models.py:515 msgid "the vendor supplying this product stock" msgstr "Prodejce dodávající tento výrobek na sklad" -#: core/models.py:606 +#: core/models.py:516 msgid "associated vendor" msgstr "Přidružený prodejce" -#: core/models.py:610 +#: core/models.py:520 msgid "final price to the customer after markups" msgstr "Konečná cena pro zákazníka po přirážkách" -#: core/models.py:611 +#: core/models.py:521 msgid "selling price" msgstr "Prodejní cena" -#: core/models.py:616 +#: core/models.py:526 msgid "the product associated with this stock entry" msgstr "Produkt spojený s touto skladovou položkou" -#: core/models.py:624 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "Související produkt" + +#: core/models.py:534 msgid "the price paid to the vendor for this product" msgstr "Cena zaplacená prodejci za tento výrobek" -#: core/models.py:625 +#: core/models.py:535 msgid "vendor purchase price" msgstr "Kupní cena prodejce" -#: core/models.py:629 +#: core/models.py:539 msgid "available quantity of the product in stock" msgstr "Dostupné množství produktu na skladě" -#: core/models.py:630 +#: core/models.py:540 msgid "quantity in stock" msgstr "Množství na skladě" -#: core/models.py:634 +#: core/models.py:544 msgid "vendor-assigned SKU for identifying the product" msgstr "SKU přidělený prodejcem pro identifikaci výrobku" -#: core/models.py:635 +#: core/models.py:545 msgid "vendor sku" msgstr "SKU prodejce" -#: core/models.py:641 +#: core/models.py:551 msgid "digital file associated with this stock if applicable" msgstr "Digitální soubor spojený s touto zásobou, je-li to vhodné" -#: core/models.py:642 +#: core/models.py:552 msgid "digital file" msgstr "Digitální soubor" -#: core/models.py:651 +#: core/models.py:561 msgid "stock entries" msgstr "Zápisy do zásob" -#: core/models.py:660 +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "Kategorie, do které tento produkt patří" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "Volitelně přiřadit tento produkt ke značce" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "Značky, které pomáhají popsat nebo seskupit tento produkt" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "Označuje, zda je tento produkt dodáván digitálně" + +#: core/models.py:626 +msgid "is product digital" +msgstr "Je produkt digitální" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "Uveďte jasný identifikační název výrobku" + +#: core/models.py:633 +msgid "product name" +msgstr "Název produktu" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "Přidejte podrobný popis produktu" + +#: core/models.py:639 +msgid "product description" +msgstr "Popis produktu" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "Číslo dílu pro tento produkt" + +#: core/models.py:647 +msgid "part number" +msgstr "Číslo dílu" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "Kategorie tohoto atributu" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "Skupina tohoto atributu" + +#: core/models.py:767 +msgid "string" +msgstr "Řetězec" + +#: core/models.py:768 +msgid "integer" +msgstr "Celé číslo" + +#: core/models.py:769 +msgid "float" +msgstr "Float" + +#: core/models.py:770 +msgid "boolean" +msgstr "Boolean" + +#: core/models.py:771 +msgid "array" +msgstr "Pole" + +#: core/models.py:772 +msgid "object" +msgstr "Objekt" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "Typ hodnoty atributu" + +#: core/models.py:775 +msgid "value type" +msgstr "Typ hodnoty" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "Název tohoto atributu" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "Název atributu" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "Atribut" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "Atribut této hodnoty" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "Konkrétní produkt spojený s hodnotou tohoto atributu" + +#: core/models.py:837 +msgid "the specific value for this attribute" +msgstr "Konkrétní hodnota tohoto atributu" + +#: core/models.py:871 +msgid "provide alternative text for the image for accessibility" +msgstr "Poskytněte alternativní text k obrázku kvůli přístupnosti." + +#: core/models.py:872 +msgid "image alt text" +msgstr "Text alt obrázku" + +#: core/models.py:875 +msgid "upload the image file for this product" +msgstr "Nahrát soubor s obrázkem tohoto produktu" + +#: core/models.py:876 core/models.py:901 +msgid "product image" +msgstr "Obrázek produktu" + +#: core/models.py:882 +msgid "determines the order in which images are displayed" +msgstr "Určuje pořadí, v jakém se obrázky zobrazují." + +#: core/models.py:883 +msgid "display priority" +msgstr "Priorita zobrazení" + +#: core/models.py:888 +msgid "the product that this image represents" +msgstr "Výrobek, který tento obrázek představuje" + +#: core/models.py:902 +msgid "product images" +msgstr "Obrázky produktů" + +#: core/models.py:943 +msgid "percentage discount for the selected products" +msgstr "Procentuální sleva na vybrané produkty" + +#: core/models.py:944 +msgid "discount percentage" +msgstr "Procento slevy" + +#: core/models.py:949 +msgid "provide a unique name for this promotion" +msgstr "Uveďte jedinečný název této propagační akce" + +#: core/models.py:950 +msgid "promotion name" +msgstr "Název akce" + +#: core/models.py:956 +msgid "promotion description" +msgstr "Popis propagace" + +#: core/models.py:961 +msgid "select which products are included in this promotion" +msgstr "Vyberte, které produkty jsou zahrnuty do této akce" + +#: core/models.py:962 +msgid "included products" +msgstr "Zahrnuté produkty" + +#: core/models.py:966 +msgid "promotion" +msgstr "Propagace" + +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "Výrobky, které uživatel označil jako požadované" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "Uživatel, který vlastní tento seznam přání" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "Majitel seznamu přání" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "Seznam přání" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} neexistuje: {product_uuid}" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "Dokumentární film" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "Dokumentární filmy" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "Nevyřešené" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "Adresní řádek pro zákazníka" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "Adresní řádek" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "Ulice" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "Okres" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "Město" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "Region" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "Poštovní směrovací číslo" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "Země" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "Geolokace Bod(Zeměpisná délka, Zeměpisná šířka)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "Úplná odpověď JSON z geokodéru pro tuto adresu" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "Uložená odpověď JSON ze služby geokódování" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "Adresa" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "Adresy" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "Jedinečný kód, který uživatel použije k uplatnění slevy." -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "Identifikátor propagačního kódu" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "Pevná výše slevy, pokud není použito procento" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "Pevná výše slevy" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "Procentuální sleva uplatněná v případě nevyužití pevné částky" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "Procentuální sleva" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "Časové razítko ukončení platnosti promokódu" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "Doba ukončení platnosti" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "Časové razítko, od kterého je tento promokód platný" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "Čas zahájení platnosti" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "Časové razítko použití promokódu, prázdné, pokud ještě nebyl použit." -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "Časové razítko použití" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "Uživatel přiřazený k tomuto promokódu, je-li to relevantní" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "Přiřazený uživatel" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "Propagační kód" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "Propagační kódy" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." @@ -1816,137 +1841,144 @@ msgstr "" "Měl by být definován pouze jeden typ slevy (částka nebo procento), nikoli " "však oba typy slev nebo žádný z nich." -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "Promo kód byl již použit" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "Neplatný typ slevy pro promocode {self.uuid}" +msgstr "Neplatný typ slevy pro promokód {self.uuid}!" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "Fakturační adresa použitá pro tuto objednávku" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "Volitelný promo kód použitý na tuto objednávku" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "Použitý promo kód" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "Dodací adresa použitá pro tuto objednávku" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "Dodací adresa" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "Aktuální stav zakázky v jejím životním cyklu" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "Stav objednávky" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" "JSON struktura oznámení pro zobrazení uživatelům, v uživatelském rozhraní " "administrátora se používá tabulkové zobrazení." -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "JSON reprezentace atributů objednávky pro tuto objednávku" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "Uživatel, který zadal objednávku" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "Uživatel" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "Časové razítko, kdy byla objednávka dokončena." -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "Kupte si čas" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "Lidsky čitelný identifikátor objednávky" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "lidsky čitelné ID" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "Objednávka" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "Uživatel smí mít vždy pouze jednu čekající objednávku!" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" -msgstr "" -"Do objednávky, která není v procesu vyřizování, nelze přidat produkty." +msgstr "Do objednávky, která není v procesu vyřizování, nelze přidat produkty." -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "Do objednávky nelze přidat neaktivní produkty" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "Nelze přidat více produktů, než je dostupné na skladě" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "Nelze odebrat produkty z objednávky, která není nevyřízená." -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "{name} neexistuje s dotazem <{query}>" +msgstr "{name} neexistuje s dotazem <{query}>!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "Promo kód neexistuje" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "Fyzické produkty můžete zakoupit pouze se zadanou dodací adresou!" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "Adresa neexistuje" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "" "V tuto chvíli nemůžete nakupovat, zkuste to prosím znovu za několik minut." -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "Neplatná hodnota síly" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "Nelze zakoupit prázdnou objednávku!" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "Bez uživatele nelze objednávku zakoupit!" + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "Uživatel bez zůstatku nemůže nakupovat se zůstatkem!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "Nedostatek finančních prostředků na dokončení objednávky" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" @@ -1954,118 +1986,121 @@ msgstr "" "bez registrace nelze nakupovat, uveďte prosím následující údaje: jméno " "zákazníka, e-mail zákazníka, telefonní číslo zákazníka." -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" msgstr "" "Neplatný způsob platby: {payment_method} z {available_payment_methods}!" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "Cena, kterou zákazník zaplatil za tento produkt v době nákupu." -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "Nákupní cena v době objednávky" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "Interní komentáře pro administrátory k tomuto objednanému produktu" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "Interní připomínky" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "Oznámení uživatele" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "JSON reprezentace atributů této položky" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "Objednané atributy produktu" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "Odkaz na nadřazenou objednávku, která obsahuje tento produkt" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "Objednávka rodičů" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "Konkrétní produkt spojený s touto objednávkou" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "Množství tohoto konkrétního produktu v objednávce" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "Množství produktu" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "Aktuální stav tohoto produktu v objednávce" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "Stav produktové řady" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "Orderproduct musí mít přiřazenou objednávku!" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "špatně zadaná akce pro zpětnou vazbu: {action}" +msgstr "Špatně zadaná akce pro zpětnou vazbu: {action}!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "nelze poskytnout zpětnou vazbu na objednávku, která nebyla přijata" -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "Stáhnout" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "Ke stažení na" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "Digitální aktivum pro nedokončenou objednávku nelze stáhnout." -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "Komentáře uživatelů o jejich zkušenostech s produktem" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "Zpětná vazba" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "" "Odkazuje na konkrétní produkt v objednávce, kterého se tato zpětná vazba " "týká." -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "Související objednávka produktu" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "Hodnocení produktu přidělené uživatelem" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "Hodnocení produktu" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "Zpětná vazba" @@ -2075,13 +2110,13 @@ msgid "" msgstr "" "pro přidání zpětné vazby musíte uvést komentář, hodnocení a uuid produktu." -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "Chyba při vytváření promokódu: {e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2090,7 +2125,7 @@ msgid "order confirmation" msgstr "Potvrzení objednávky" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2101,13 +2136,14 @@ msgstr "Logo" #: core/templates/shipped_order_delivered_email.html:100 #, python-format msgid "hello %(order.user.first_name)s," -msgstr "Hello %(order.user.first_name)s," +msgstr "Ahoj %(order.user.first_name)s," #: core/templates/digital_order_created_email.html:102 #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" msgstr "" "Děkujeme vám za vaši objednávku #%(order.pk)s! S potěšením Vám oznamujeme, " @@ -2115,14 +2151,14 @@ msgstr "" "objednávce:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "Celkem" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2145,20 +2181,20 @@ msgid "best regards,
the %(config.PROJECT_NAME)s team" msgstr "S pozdravem,
tým %(config.PROJECT_NAME)s" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "Všechna práva vyhrazena" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "Dodaná objednávka" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "Ahoj %(user_first_name)s," -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" @@ -2167,7 +2203,7 @@ msgstr "" "Úspěšně jsme zpracovali vaši objednávku №%(order_uuid)s! Níže jsou uvedeny " "podrobnosti vaší objednávky:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2175,12 +2211,12 @@ msgstr "" "další\n" " informace" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "Hodnota" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -2189,7 +2225,7 @@ msgstr "" "V případě dotazů se můžete obrátit na naši podporu na adrese " "%(contact_email)s." -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "S pozdravem,
tým %(project_name)s" @@ -2201,7 +2237,8 @@ msgstr "Klíč" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" msgstr "" "Děkujeme vám za vaši objednávku! S potěšením potvrzujeme váš nákup. Níže " @@ -2221,7 +2258,7 @@ msgstr "Vaše objednávka bude doručena na následující adresu:" #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "S pozdravem,
tým %(config.PROJECT_NAME)s" +msgstr "S pozdravem,
Tým %(config.PROJECT_NAME)s" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2240,30 +2277,20 @@ msgstr "Jsou vyžadována data i časový limit" msgid "invalid timeout value, it must be between 0 and 216000 seconds" msgstr "Nesprávná hodnota timeoutu, musí být v rozmezí 0 až 216000 sekund." -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model} musí být model" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data} musí být objekt seznamu" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | Kontakt iniciován" +msgstr "{config.PROJECT_NAME} | kontaktujte nás inicioval" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" msgstr "{config.PROJECT_NAME} | Potvrzení objednávky" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" -msgstr "{config.PROJECT_NAME} | Dodaná objednávka" +msgstr "{config.PROJECT_NAME} | Objednávka doručena" #: core/utils/messages.py:3 msgid "you do not have permission to perform this action." @@ -2283,15 +2310,15 @@ msgstr "" msgid "invalid phone number format" msgstr "Nesprávný formát telefonního čísla" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "Digitální aktivum můžete stáhnout pouze jednou" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "favicon nebyl nalezen" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "Chyba v zeměpisném kódování: {e}" diff --git a/core/locale/da_DK/LC_MESSAGES/django.mo b/core/locale/da_DK/LC_MESSAGES/django.mo index 3364a06b..1a540d7e 100644 Binary files a/core/locale/da_DK/LC_MESSAGES/django.mo and b/core/locale/da_DK/LC_MESSAGES/django.mo differ diff --git a/core/locale/da_DK/LC_MESSAGES/django.po b/core/locale/da_DK/LC_MESSAGES/django.po index 1ed0e4c7..e185395c 100644 --- a/core/locale/da_DK/LC_MESSAGES/django.po +++ b/core/locale/da_DK/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,120 +13,117 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "Unikt ID" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "Unikt ID bruges til sikkert at identificere ethvert databaseobjekt" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "Er aktiv" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" +"if set to false, this object can't be seen by users without needed permission" msgstr "" "Hvis det er sat til false, kan dette objekt ikke ses af brugere uden den " "nødvendige tilladelse." -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "Oprettet" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "Da objektet første gang dukkede op i databasen" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "Modificeret" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "Hvornår objektet sidst blev redigeret" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "Oversættelser" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "Generelt" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "Relationer" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "Metadata" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "Tidsstempler" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" -msgstr "Aktivér udvalgte %(verbose_name_plural)s" +msgstr "Aktivér valgt %(verbose_name_plural)s." -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)s aktiveret med succes!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "Udvalgte varer er blevet aktiveret!" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" -msgstr "Deaktiver udvalgte %(verbose_name_plural)s" +msgstr "Deaktiver valgte %(verbose_name_plural)s." -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "%(verbose_name_plural)s deaktiveret med succes." +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "Udvalgte varer er blevet deaktiveret!" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "Attributværdi" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "Attributværdier" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "Billede" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "Billeder" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "Lager" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "Aktier" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "Bestil produkt" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "Bestil produkter" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "Børn" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "Konfig" @@ -178,7 +175,7 @@ msgstr "Momental" msgid "successful" msgstr "Succesfuld" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "Cache-I/O" @@ -188,7 +185,8 @@ msgid "" "apply key, data and timeout with authentication to write data to cache." msgstr "" "Anvend kun en nøgle til at læse tilladte data fra cachen.\n" -"Anvend nøgle, data og timeout med autentificering for at skrive data til cachen." +"Anvend nøgle, data og timeout med autentificering for at skrive data til " +"cachen." #: core/docs/drf/views.py:32 msgid "get a list of supported languages" @@ -202,7 +200,7 @@ msgstr "Hent applikationens eksponerbare parametre" msgid "send a message to the support team" msgstr "Send en besked til supportteamet" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "Anmod om en CORSed URL. Kun https er tilladt." @@ -245,8 +243,7 @@ msgstr "" "attributter" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" +msgid "rewrite some fields of an existing attribute group saving non-editables" msgstr "" "Omskriv nogle felter i en eksisterende attributgruppe og gem ikke-" "redigerbare felter" @@ -299,11 +296,10 @@ msgstr "" "Omskriv en eksisterende attributværdi, der gemmer ikke-redigerbare filer" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" +msgid "rewrite some fields of an existing attribute value saving non-editables" msgstr "" -"Omskriv nogle felter i en eksisterende attributværdi og gem ikke-redigerbare" -" felter" +"Omskriv nogle felter i en eksisterende attributværdi og gem ikke-redigerbare " +"felter" #: core/docs/drf/viewsets.py:124 msgid "list all categories (simple view)" @@ -337,17 +333,16 @@ msgstr "Liste over alle kategorier (enkel visning)" #: core/docs/drf/viewsets.py:152 msgid "for non-staff users, only their own orders are returned." -msgstr "" -"For ikke-ansatte brugere er det kun deres egne ordrer, der returneres." +msgstr "For ikke-ansatte brugere er det kun deres egne ordrer, der returneres." #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" "Substringsøgning uden brug af store og små bogstaver på tværs af " -"human_readable_id, order_products.product.name og " -"order_products.product.partnumber" +"human_readable_id, order_products.product.name og order_products.product." +"partnumber" #: core/docs/drf/viewsets.py:165 msgid "Filter orders with buy_time >= this ISO 8601 datetime" @@ -379,13 +374,13 @@ msgstr "Filtrer efter ordrestatus (case-insensitive substring match)" #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" "Bestil efter en af: uuid, human_readable_id, user_email, user, status, " -"created, modified, buy_time, random. Præfiks med '-' for faldende rækkefølge" -" (f.eks. '-buy_time')." +"created, modified, buy_time, random. Præfiks med '-' for faldende rækkefølge " +"(f.eks. '-buy_time')." #: core/docs/drf/viewsets.py:210 msgid "retrieve a single order (detailed view)" @@ -427,7 +422,7 @@ msgstr "" "ved hjælp af brugerens saldo; hvis `force_payment` bruges, igangsættes en " "transaktion." -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "Køb en ordre uden at oprette en konto" @@ -535,8 +530,7 @@ msgstr "Fjern et produkt fra ønskelisten" #: core/docs/drf/viewsets.py:314 msgid "removes a product from an wishlist using the provided `product_uuid`" msgstr "" -"Fjerner et produkt fra en ønskeliste ved hjælp af den angivne " -"`product_uuid`." +"Fjerner et produkt fra en ønskeliste ved hjælp af den angivne `product_uuid`." #: core/docs/drf/viewsets.py:319 msgid "add many products to wishlist" @@ -563,18 +557,28 @@ msgstr "" msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "Filtrer efter et eller flere attributnavn/værdipar. \n" "- **Syntaks**: `attr_name=method-value[;attr2=method2-value2]...`.\n" -"- **Metoder** (standard er `icontains`, hvis udeladt): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`.\n" -"- Værdiindtastning**: JSON forsøges først (så du kan sende lister/dikter), `true`/`false` for booleans, heltal, floats; ellers behandles de som strenge. \n" -"- **Base64**: præfiks med `b64-` for URL-sikker base64-kodning af den rå værdi. \n" +"- **Metoder** (standard er `icontains`, hvis udeladt): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`.\n" +"- Værdiindtastning**: JSON forsøges først (så du kan sende lister/dikter), " +"`true`/`false` for booleans, heltal, floats; ellers behandles de som " +"strenge. \n" +"- **Base64**: præfiks med `b64-` for URL-sikker base64-kodning af den rå " +"værdi. \n" "Eksempler på dette: \n" "`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`,\n" "`b64-description=icontains-aGVhdC1jb2xk`." @@ -629,10 +633,12 @@ msgstr "(præcis) Digital vs. fysisk" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" -"Kommasepareret liste over felter, der skal sorteres efter. Præfiks med `-` for faldende. \n" +"Kommasepareret liste over felter, der skal sorteres efter. Præfiks med `-` " +"for faldende. \n" "**Tilladt:** uuid, vurdering, navn, slug, oprettet, ændret, pris, tilfældig" #: core/docs/drf/viewsets.py:441 @@ -758,7 +764,7 @@ msgstr "slette en ordre-produkt-relation" msgid "add or remove feedback on an order–product relation" msgstr "tilføje eller fjerne feedback på en ordre-produkt-relation" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "Der er ikke angivet noget søgeord." @@ -806,8 +812,8 @@ msgstr "Egenskaber" msgid "Quantity" msgstr "Mængde" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "Snegl" @@ -869,220 +875,242 @@ msgstr "Niveau" msgid "Product UUID" msgstr "Produkt UUID" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "Nøgle til at lede efter i eller lægge i cachen" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "Data, der skal gemmes i cachen" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "Timeout i sekunder for at lægge data i cachen" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "Cachelagrede data" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "Cameliserede JSON-data fra den ønskede URL" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "Kun URL'er, der starter med http(s)://, er tilladt." -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "Tilføj et produkt til ordren" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "Ordre {order_uuid} ikke fundet" +msgstr "Ordre {order_uuid} ikke fundet!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "Fjern et produkt fra ordren" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "Fjern alle produkter fra ordren" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "Køb en ordre" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "Angiv enten order_uuid eller order_hr_id - det udelukker hinanden!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "Forkert type kom fra metoden order.buy(): {type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "Udfør en handling på en liste af produkter i ordren" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "Fjern/tilføj" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "Handlingen skal være enten \"tilføj\" eller \"fjern\"!" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "Udfør en handling på en liste af produkter i ønskelisten" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "Angiv venligst værdien `wishlist_uuid`." + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "Ønskeliste {wishlist_uuid} ikke fundet!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "Tilføj et produkt til ordren" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "Ønskeliste {wishlist_uuid} ikke fundet" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "Fjern et produkt fra ordren" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "Fjern et produkt fra ordren" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "Fjern et produkt fra ordren" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "Køb en ordre" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" msgstr "" -"Send venligst attributterne som en streng formateret som " -"attr1=værdi1,attr2=værdi2" +"Send venligst attributterne som en streng formateret som attr1=værdi1," +"attr2=værdi2" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "Tilføj eller slet en feedback til ordreproduktet" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "Handlingen skal være enten `add` eller `remove`!" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "Ordreprodukt {order_product_uuid} ikke fundet!" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "Original adressestreng leveret af brugeren" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} findes ikke: {uuid}" +msgstr "{name} findes ikke: {uuid}!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "Grænsen skal være mellem 1 og 10" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - fungerer som en charme" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "Egenskaber" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "Grupperede attributter" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "Grupper af attributter" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "Kategorier" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "Mærker" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "Kategorier" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "Markup-procentdel" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "" -"Hvilke attributter og værdier, der kan bruges til at filtrere denne " -"kategori." +"Hvilke attributter og værdier, der kan bruges til at filtrere denne kategori." -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." +#: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." msgstr "" "Minimums- og maksimumspriser for produkter i denne kategori, hvis de er " "tilgængelige." -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "Tags for denne kategori" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "Produkter i denne kategori" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "Leverandører" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "Breddegrad (Y-koordinat)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "Længdegrad (X-koordinat)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "Sådan gør du" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "" "Vurderingsværdi fra 1 til 10, inklusive, eller 0, hvis den ikke er " "indstillet." -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "Repræsenterer feedback fra en bruger." -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "Meddelelser" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "Download url for dette ordreprodukt, hvis det er relevant" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "En liste over bestillingsprodukter i denne ordre" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "Faktureringsadresse" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" @@ -1090,732 +1118,729 @@ msgstr "" "Leveringsadresse for denne ordre, lad den være tom, hvis den er den samme " "som faktureringsadressen, eller hvis den ikke er relevant" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "Samlet pris for denne ordre" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "Samlet antal produkter i ordren" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "Er alle produkterne i ordren digitale?" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "Transaktioner for denne ordre" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "Bestillinger" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "Billed-URL" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "Produktets billeder" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "Kategori" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "Tilbagemeldinger" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "Brand" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "Attributgrupper" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "Pris" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "Mængde" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "Antal tilbagemeldinger" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "Produkter" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "Promokoder" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "Produkter til salg" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "Kampagner" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "Leverandør" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "Produkt" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "Produkter på ønskelisten" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "Ønskelister" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "Mærkede produkter" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "Produktmærker" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "Tagged kategorier" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "Kategoriernes tags" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "Projektets navn" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "Virksomhedens e-mail" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "Virksomhedens navn" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "Virksomhedens adresse" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "Virksomhedens telefonnummer" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "" "'e-mail fra', nogle gange skal den bruges i stedet for værtsbrugerværdien" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "E-mail-værtsbruger" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "Maksimalt beløb til betaling" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "Minimumsbeløb for betaling" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "Analytiske data" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "Data om reklamer" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "Konfiguration" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "Sprogkode" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "Sprogets navn" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "Sprogflag, hvis det findes :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "Få en liste over understøttede sprog" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "Søgeresultater for produkter" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "Søgeresultater for produkter" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "Forælder til denne gruppe" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "Overordnet attributgruppe" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "Attributgruppens navn" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "Attributgruppe" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" "Gemmer legitimationsoplysninger og slutpunkter, der er nødvendige for " "leverandørens API-kommunikation" -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "Oplysninger om godkendelse" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "Definer markeringen for produkter, der hentes fra denne leverandør" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "Sælgerens markup-procentdel" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "Navn på denne leverandør" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "Leverandørens navn" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "Intern tag-identifikator for produkttagget" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "Tag-navn" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "Brugervenligt navn til produktmærket" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "Navn på tag-visning" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "Produktmærke" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "Kategori-tag" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "Kategori-tags" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "Upload et billede, der repræsenterer denne kategori" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "Kategori billede" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "Definer en markup-procentdel for produkter i denne kategori" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "Forælder til denne kategori for at danne en hierarkisk struktur" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "Overordnet kategori" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "Navn på kategori" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "Giv et navn til denne kategori" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "Tilføj en detaljeret beskrivelse af denne kategori" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "Beskrivelse af kategori" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "tags, der hjælper med at beskrive eller gruppere denne kategori" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "Prioritet" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "Navnet på dette mærke" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "Varemærke" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "Upload et logo, der repræsenterer dette brand" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "Brandets lille image" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "Upload et stort logo, der repræsenterer dette brand" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "Brandets store image" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "Tilføj en detaljeret beskrivelse af brandet" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "Varemærkebeskrivelse" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "Valgfrie kategorier, som dette brand er forbundet med" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "Kategorier" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "Kategori, som dette produkt tilhører" - -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "Tilknyt eventuelt dette produkt til et brand" - -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "Tags, der hjælper med at beskrive eller gruppere dette produkt" - -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "Angiver, om dette produkt leveres digitalt" - -#: core/models.py:351 -msgid "is product digital" -msgstr "Er produktet digitalt?" - -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "Giv produktet et klart identificerende navn" - -#: core/models.py:358 -msgid "product name" -msgstr "Produktets navn" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "Tilføj en detaljeret beskrivelse af produktet" - -#: core/models.py:364 -msgid "product description" -msgstr "Produktbeskrivelse" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "Reservedelsnummer for dette produkt" - -#: core/models.py:372 -msgid "part number" -msgstr "Varenummer" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "Kategori for denne attribut" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "Gruppe af denne attribut" - -#: core/models.py:465 -msgid "string" -msgstr "Streng" - -#: core/models.py:466 -msgid "integer" -msgstr "Heltal" - -#: core/models.py:467 -msgid "float" -msgstr "Flyder" - -#: core/models.py:468 -msgid "boolean" -msgstr "Boolsk" - -#: core/models.py:469 -msgid "array" -msgstr "Array" - -#: core/models.py:470 -msgid "object" -msgstr "Objekt" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "Type af attributtens værdi" - -#: core/models.py:473 -msgid "value type" -msgstr "Værditype" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "Navn på denne attribut" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "Attributtens navn" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "Attribut" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "Attribut for denne værdi" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "Det specifikke produkt, der er knyttet til denne attributs værdi" - -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 -msgid "associated product" -msgstr "Tilknyttet produkt" - -#: core/models.py:512 -msgid "the specific value for this attribute" -msgstr "Den specifikke værdi for denne attribut" - -#: core/models.py:528 -msgid "provide alternative text for the image for accessibility" -msgstr "Giv alternativ tekst til billedet af hensyn til tilgængeligheden" - -#: core/models.py:529 -msgid "image alt text" -msgstr "Billedets alt-tekst" - -#: core/models.py:532 -msgid "upload the image file for this product" -msgstr "Upload billedfilen til dette produkt" - -#: core/models.py:533 core/models.py:558 -msgid "product image" -msgstr "Produktbillede" - -#: core/models.py:539 -msgid "determines the order in which images are displayed" -msgstr "Bestemmer den rækkefølge, billederne vises i" - -#: core/models.py:540 -msgid "display priority" -msgstr "Skærm-prioritet" - -#: core/models.py:545 -msgid "the product that this image represents" -msgstr "Det produkt, som dette billede repræsenterer" - -#: core/models.py:559 -msgid "product images" -msgstr "Produktbilleder" - -#: core/models.py:567 -msgid "percentage discount for the selected products" -msgstr "Procentvis rabat for de valgte produkter" - -#: core/models.py:568 -msgid "discount percentage" -msgstr "Rabatprocent" - -#: core/models.py:573 -msgid "provide a unique name for this promotion" -msgstr "Giv et unikt navn til denne kampagne" - -#: core/models.py:574 -msgid "promotion name" -msgstr "Navn på kampagne" - -#: core/models.py:580 -msgid "promotion description" -msgstr "Beskrivelse af kampagnen" - -#: core/models.py:585 -msgid "select which products are included in this promotion" -msgstr "Vælg, hvilke produkter der er inkluderet i denne kampagne" - -#: core/models.py:586 -msgid "included products" -msgstr "Inkluderede produkter" - -#: core/models.py:590 -msgid "promotion" -msgstr "Forfremmelse" - -#: core/models.py:605 +#: core/models.py:515 msgid "the vendor supplying this product stock" msgstr "Den leverandør, der leverer dette produkt, lagerfører" -#: core/models.py:606 +#: core/models.py:516 msgid "associated vendor" msgstr "Tilknyttet leverandør" -#: core/models.py:610 +#: core/models.py:520 msgid "final price to the customer after markups" msgstr "Endelig pris til kunden efter tillæg" -#: core/models.py:611 +#: core/models.py:521 msgid "selling price" msgstr "Salgspris" -#: core/models.py:616 +#: core/models.py:526 msgid "the product associated with this stock entry" msgstr "Det produkt, der er knyttet til denne lagerpost" -#: core/models.py:624 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "Tilknyttet produkt" + +#: core/models.py:534 msgid "the price paid to the vendor for this product" msgstr "Den pris, der er betalt til sælgeren for dette produkt" -#: core/models.py:625 +#: core/models.py:535 msgid "vendor purchase price" msgstr "Leverandørens købspris" -#: core/models.py:629 +#: core/models.py:539 msgid "available quantity of the product in stock" msgstr "Tilgængelig mængde af produktet på lager" -#: core/models.py:630 +#: core/models.py:540 msgid "quantity in stock" msgstr "Antal på lager" -#: core/models.py:634 +#: core/models.py:544 msgid "vendor-assigned SKU for identifying the product" msgstr "Leverandørtildelt SKU til identifikation af produktet" -#: core/models.py:635 +#: core/models.py:545 msgid "vendor sku" msgstr "Leverandørens SKU" -#: core/models.py:641 +#: core/models.py:551 msgid "digital file associated with this stock if applicable" msgstr "Digital fil knyttet til dette lager, hvis relevant" -#: core/models.py:642 +#: core/models.py:552 msgid "digital file" msgstr "Digital fil" -#: core/models.py:651 +#: core/models.py:561 msgid "stock entries" msgstr "Lagerposteringer" -#: core/models.py:660 +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "Kategori, som dette produkt tilhører" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "Tilknyt eventuelt dette produkt til et brand" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "Tags, der hjælper med at beskrive eller gruppere dette produkt" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "Angiver, om dette produkt leveres digitalt" + +#: core/models.py:626 +msgid "is product digital" +msgstr "Er produktet digitalt?" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "Giv produktet et klart identificerende navn" + +#: core/models.py:633 +msgid "product name" +msgstr "Produktets navn" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "Tilføj en detaljeret beskrivelse af produktet" + +#: core/models.py:639 +msgid "product description" +msgstr "Produktbeskrivelse" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "Reservedelsnummer for dette produkt" + +#: core/models.py:647 +msgid "part number" +msgstr "Varenummer" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "Kategori for denne attribut" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "Gruppe af denne attribut" + +#: core/models.py:767 +msgid "string" +msgstr "Streng" + +#: core/models.py:768 +msgid "integer" +msgstr "Heltal" + +#: core/models.py:769 +msgid "float" +msgstr "Flyder" + +#: core/models.py:770 +msgid "boolean" +msgstr "Boolsk" + +#: core/models.py:771 +msgid "array" +msgstr "Array" + +#: core/models.py:772 +msgid "object" +msgstr "Objekt" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "Type af attributtens værdi" + +#: core/models.py:775 +msgid "value type" +msgstr "Værditype" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "Navn på denne attribut" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "Attributtens navn" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "Attribut" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "Attribut for denne værdi" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "Det specifikke produkt, der er knyttet til denne attributs værdi" + +#: core/models.py:837 +msgid "the specific value for this attribute" +msgstr "Den specifikke værdi for denne attribut" + +#: core/models.py:871 +msgid "provide alternative text for the image for accessibility" +msgstr "Giv alternativ tekst til billedet af hensyn til tilgængeligheden" + +#: core/models.py:872 +msgid "image alt text" +msgstr "Billedets alt-tekst" + +#: core/models.py:875 +msgid "upload the image file for this product" +msgstr "Upload billedfilen til dette produkt" + +#: core/models.py:876 core/models.py:901 +msgid "product image" +msgstr "Produktbillede" + +#: core/models.py:882 +msgid "determines the order in which images are displayed" +msgstr "Bestemmer den rækkefølge, billederne vises i" + +#: core/models.py:883 +msgid "display priority" +msgstr "Skærm-prioritet" + +#: core/models.py:888 +msgid "the product that this image represents" +msgstr "Det produkt, som dette billede repræsenterer" + +#: core/models.py:902 +msgid "product images" +msgstr "Produktbilleder" + +#: core/models.py:943 +msgid "percentage discount for the selected products" +msgstr "Procentvis rabat for de valgte produkter" + +#: core/models.py:944 +msgid "discount percentage" +msgstr "Rabatprocent" + +#: core/models.py:949 +msgid "provide a unique name for this promotion" +msgstr "Giv et unikt navn til denne kampagne" + +#: core/models.py:950 +msgid "promotion name" +msgstr "Navn på kampagne" + +#: core/models.py:956 +msgid "promotion description" +msgstr "Beskrivelse af kampagnen" + +#: core/models.py:961 +msgid "select which products are included in this promotion" +msgstr "Vælg, hvilke produkter der er inkluderet i denne kampagne" + +#: core/models.py:962 +msgid "included products" +msgstr "Inkluderede produkter" + +#: core/models.py:966 +msgid "promotion" +msgstr "Forfremmelse" + +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "Produkter, som brugeren har markeret som ønskede" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "Bruger, der ejer denne ønskeliste" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "Ønskelistens ejer" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "Ønskeliste" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} findes ikke: {product_uuid}." - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "Dokumentarfilm" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "Dokumentarfilm" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "Uafklaret" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "Adresselinje til kunden" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "Adresselinje" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "Gade" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "Distrikt" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "By" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "Region" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "Postnummer" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "Land" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "Geolokaliseringspunkt (længdegrad, breddegrad)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "Fuldt JSON-svar fra geokoderen for denne adresse" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "Gemt JSON-svar fra geokodningstjenesten" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "Adresse" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "Adresser" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "Unik kode, der bruges af en bruger til at indløse en rabat" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "Identifikator for kampagnekode" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "Fast rabatbeløb anvendes, hvis procent ikke bruges" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "Fast rabatbeløb" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "Procentvis rabat, hvis det faste beløb ikke bruges" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "Procentvis rabat" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "Tidsstempel, når promokoden udløber" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "Slut gyldighedstid" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "Tidsstempel, hvorfra denne promokode er gyldig" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "Start gyldighedstid" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "" "Tidsstempel, hvor promokoden blev brugt, blank, hvis den ikke er brugt endnu" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "Tidsstempel for brug" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "Bruger tildelt denne promokode, hvis relevant" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "Tildelt bruger" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "Kampagnekode" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "Kampagnekoder" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." @@ -1823,137 +1848,145 @@ msgstr "" "Der skal kun defineres én type rabat (beløb eller procent), men ikke begge " "eller ingen af dem." -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "Promokoden er allerede blevet brugt" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "Ugyldig rabattype for promokode {self.uuid}." +msgstr "Ugyldig rabattype for promokode {self.uuid}!" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "Den faktureringsadresse, der bruges til denne ordre" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "Valgfri kampagnekode anvendt på denne ordre" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "Anvendt kampagnekode" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "Den leveringsadresse, der er brugt til denne ordre" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "Leveringsadresse" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "Ordrens aktuelle status i dens livscyklus" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "Bestillingsstatus" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" -"JSON-struktur af meddelelser, der skal vises til brugerne, i admin UI bruges" -" tabelvisningen" +"JSON-struktur af meddelelser, der skal vises til brugerne, i admin UI bruges " +"tabelvisningen" -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "JSON-repræsentation af ordreattributter for denne ordre" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "Den bruger, der har afgivet ordren" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "Bruger" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "Tidsstemplet for, hvornår ordren blev afsluttet" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "Køb tid" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "En menneskeligt læsbar identifikator for ordren" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "menneskeligt læsbart ID" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "Bestil" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "En bruger må kun have én afventende ordre ad gangen!" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "Du kan ikke tilføje produkter til en ordre, der ikke er i gang." -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "Du kan ikke tilføje inaktive produkter til en ordre" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "Du kan ikke tilføje flere produkter, end der er på lager" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "" -"Du kan ikke fjerne produkter fra en ordre, der ikke er en igangværende " -"ordre." +"Du kan ikke fjerne produkter fra en ordre, der ikke er en igangværende ordre." -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "{name} findes ikke med forespørgsel <{query}>." +msgstr "{name} findes ikke med forespørgslen <{query}>!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "Promokode findes ikke" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "Du kan kun købe fysiske produkter med angivet leveringsadresse!" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "Adressen findes ikke" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "Du kan ikke købe i øjeblikket, prøv venligst igen om et par minutter." -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "Ugyldig kraftværdi" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "Du kan ikke købe en tom ordre!" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "" +"Du kan ikke fjerne produkter fra en ordre, der ikke er en igangværende ordre." + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "En bruger uden saldo kan ikke købe med saldo!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "Utilstrækkelige midler til at gennemføre ordren" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" @@ -1961,120 +1994,121 @@ msgstr "" "du kan ikke købe uden registrering, angiv venligst følgende oplysninger: " "kundens navn, kundens e-mail, kundens telefonnummer" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" msgstr "" "Ugyldig betalingsmetode: {payment_method} fra {available_payment_methods}!" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "Den pris, som kunden har betalt for dette produkt på købstidspunktet" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "Købspris på bestillingstidspunktet" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "Interne kommentarer til administratorer om dette bestilte produkt" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "Interne kommentarer" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "Notifikationer til brugere" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "JSON-repræsentation af dette elements attributter" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "Bestilte produktattributter" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "Henvisning til den overordnede ordre, der indeholder dette produkt" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "Forældreordre" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "Det specifikke produkt, der er knyttet til denne ordrelinje" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "Mængde af dette specifikke produkt i ordren" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "Produktmængde" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "Aktuel status for dette produkt i bestillingen" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "Status for produktlinje" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "Orderproduct skal have en tilknyttet ordre!" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "forkert handling angivet for feedback: {action}." +msgstr "Forkert handling angivet for feedback: {action}!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "" -"Du kan ikke fjerne produkter fra en ordre, der ikke er en igangværende " -"ordre." +"Du kan ikke fjerne produkter fra en ordre, der ikke er en igangværende ordre." -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "Download" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "Downloads" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "Du kan ikke downloade et digitalt aktiv for en ikke-færdiggjort ordre" -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "Brugernes kommentarer om deres oplevelse med produktet" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "Kommentarer til feedback" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "" -"Henviser til det specifikke produkt i en ordre, som denne feedback handler " -"om" +"Henviser til det specifikke produkt i en ordre, som denne feedback handler om" -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "Relateret ordreprodukt" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "Brugertildelt vurdering af produktet" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "Produktvurdering" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "Feedback" @@ -2085,13 +2119,13 @@ msgstr "" "Du skal angive en kommentar, en vurdering og et produkt-uid for at tilføje " "feedback." -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "Fejl under oprettelse af promokode: {e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2100,7 +2134,7 @@ msgid "order confirmation" msgstr "Ordrebekræftelse" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2117,21 +2151,22 @@ msgstr "Hej %(order.user.first_name)s," #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" msgstr "" "Tak for din ordre #%(order.pk)s! Vi er glade for at kunne informere dig om, " "at vi har taget din ordre i brug. Nedenfor er detaljerne om din ordre:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "I alt" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2151,23 +2186,23 @@ msgstr "" #: core/templates/digital_order_created_email.html:133 #, python-format msgid "best regards,
the %(config.PROJECT_NAME)s team" -msgstr "Med venlig hilsen,
%(config.PROJECT_NAME)s team" +msgstr "Med venlig hilsen,
teamet %(config.PROJECT_NAME)s." #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "Alle rettigheder forbeholdes" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "Order Delivered" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "Hej %(user_first_name)s," -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" @@ -2176,7 +2211,7 @@ msgstr "" "Vi har behandlet din ordre №%(order_uuid)s! Nedenfor er detaljerne om din " "ordre:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2184,12 +2219,12 @@ msgstr "" "yderligere\n" " oplysninger" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "Værdi" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -2198,10 +2233,10 @@ msgstr "" "Hvis du har spørgsmål, er du velkommen til at kontakte vores support på " "%(contact_email)s." -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Med venlig hilsen,
%(project_name)s team" +msgstr "Med venlig hilsen,
teamet %(project_name)s." #: core/templates/json_table_widget.html:5 msgid "key" @@ -2210,7 +2245,8 @@ msgstr "Nøgle" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" msgstr "" "Tak for din bestilling! Vi er glade for at kunne bekræfte dit køb. Nedenfor " @@ -2230,7 +2266,7 @@ msgstr "Din ordre vil blive leveret til følgende adresse:" #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "Med venlig hilsen %(config.PROJECT_NAME)s team" +msgstr "De bedste hilsner,
The %(config.PROJECT_NAME)s team" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2249,30 +2285,20 @@ msgstr "Både data og timeout er påkrævet" msgid "invalid timeout value, it must be between 0 and 216000 seconds" msgstr "Ugyldig timeout-værdi, den skal være mellem 0 og 216000 sekunder" -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model} skal være model" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data} skal være et listeobjekt" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | Kontakt os indledt" +msgstr "{config.PROJECT_NAME} | kontakt os påbegyndt" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" msgstr "{config.PROJECT_NAME} | Ordrebekræftelse" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" -msgstr "{config.PROJECT_NAME} | Ordre leveret" +msgstr "{config.PROJECT_NAME} | Order Delivered" #: core/utils/messages.py:3 msgid "you do not have permission to perform this action." @@ -2286,22 +2312,21 @@ msgstr "Parameteren NOMINATIM_URL skal være konfigureret!" #, python-brace-format msgid "image dimensions should not exceed w{max_width} x h{max_height} pixels" msgstr "" -"Billedets dimensioner bør ikke overstige w{max_width} x h{max_height} " -"pixels." +"Billedets dimensioner bør ikke overstige w{max_width} x h{max_height} pixels." #: core/validators.py:22 msgid "invalid phone number format" msgstr "Ugyldigt telefonnummerformat" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "Du kan kun downloade det digitale aktiv én gang" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "Favicon ikke fundet" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "Fejl i geokodning: {e}" diff --git a/core/locale/de_DE/LC_MESSAGES/django.mo b/core/locale/de_DE/LC_MESSAGES/django.mo index 394ab449..fe91eb6e 100644 Binary files a/core/locale/de_DE/LC_MESSAGES/django.mo and b/core/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/core/locale/de_DE/LC_MESSAGES/django.po b/core/locale/de_DE/LC_MESSAGES/django.po index c3c5f7b7..51822d39 100644 --- a/core/locale/de_DE/LC_MESSAGES/django.po +++ b/core/locale/de_DE/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,122 +13,119 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "Eindeutige ID" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "" "Eindeutige ID wird zur sicheren Identifizierung jedes Datenbankobjekts " "verwendet" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "Ist aktiv" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" +"if set to false, this object can't be seen by users without needed permission" msgstr "" "Wenn auf false gesetzt, kann dieses Objekt von Benutzern ohne die " "erforderliche Berechtigung nicht gesehen werden." -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "Erstellt" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "Wann das Objekt zum ersten Mal in der Datenbank erschienen ist" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "Geändert" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "Wann das Objekt zuletzt bearbeitet wurde" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "Übersetzungen" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "Allgemein" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "Beziehungen" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "Metadaten" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "Zeitstempel" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" msgstr "Ausgewählte %(verbose_name_plural)s aktivieren" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)s erfolgreich aktiviert!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "Ausgewählte Artikel wurden aktiviert!" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" msgstr "Ausgewählte %(verbose_name_plural)s deaktivieren" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "%(verbose_name_plural)s wurde erfolgreich deaktiviert." +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "Ausgewählte Artikel wurden deaktiviert!" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "Attribut Wert" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "Attribut Werte" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "Bild" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "Bilder" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "Lagerbestand" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "Bestände" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "Produkt bestellen" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "Produkte bestellen" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "Kinder" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "Konfigurieren Sie" @@ -180,7 +177,7 @@ msgstr "Momente" msgid "successful" msgstr "Erfolgreich" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "Cache I/O" @@ -189,8 +186,10 @@ msgid "" "apply only a key to read permitted data from cache.\n" "apply key, data and timeout with authentication to write data to cache." msgstr "" -"Wenden Sie nur einen Schlüssel an, um erlaubte Daten aus dem Cache zu lesen.\n" -"Schlüssel, Daten und Timeout mit Authentifizierung anwenden, um Daten in den Cache zu schreiben." +"Wenden Sie nur einen Schlüssel an, um erlaubte Daten aus dem Cache zu " +"lesen.\n" +"Schlüssel, Daten und Timeout mit Authentifizierung anwenden, um Daten in den " +"Cache zu schreiben." #: core/docs/drf/views.py:32 msgid "get a list of supported languages" @@ -204,7 +203,7 @@ msgstr "Abrufen der exponierbaren Parameter der Anwendung" msgid "send a message to the support team" msgstr "Senden Sie eine Nachricht an das Support-Team" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "Fordern Sie eine CORS-gesicherte URL an. Nur https erlaubt." @@ -247,8 +246,7 @@ msgstr "" "Editierbarkeit" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" +msgid "rewrite some fields of an existing attribute group saving non-editables" msgstr "" "Umschreiben einiger Felder einer bestehenden Attributgruppe, wobei nicht " "editierbare Felder gespeichert werden" @@ -278,8 +276,8 @@ msgstr "" #: core/docs/drf/viewsets.py:90 msgid "rewrite some fields of an existing attribute saving non-editables" msgstr "" -"Umschreiben einiger Felder eines vorhandenen Attributs, um nicht editierbare" -" Daten zu speichern" +"Umschreiben einiger Felder eines vorhandenen Attributs, um nicht editierbare " +"Daten zu speichern" #: core/docs/drf/viewsets.py:97 msgid "list all attribute values (simple view)" @@ -304,8 +302,7 @@ msgstr "" "Editierbarkeit" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" +msgid "rewrite some fields of an existing attribute value saving non-editables" msgstr "" "Umschreiben einiger Felder eines vorhandenen Attributwerts, wobei nicht " "bearbeitbare Daten gespeichert werden" @@ -334,8 +331,8 @@ msgstr "" #: core/docs/drf/viewsets.py:144 msgid "rewrite some fields of an existing category saving non-editables" msgstr "" -"Umschreiben einiger Felder einer bestehenden Kategorie, um nicht editierbare" -" Daten zu speichern" +"Umschreiben einiger Felder einer bestehenden Kategorie, um nicht editierbare " +"Daten zu speichern" #: core/docs/drf/viewsets.py:151 msgid "list all orders (simple view)" @@ -348,12 +345,12 @@ msgstr "" #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" "Groß- und Kleinschreibung unempfindliche Teilstringsuche über " -"human_readable_id, order_products.product.name und " -"order_products.product.partnumber" +"human_readable_id, order_products.product.name und order_products.product." +"partnumber" #: core/docs/drf/viewsets.py:165 msgid "Filter orders with buy_time >= this ISO 8601 datetime" @@ -389,9 +386,9 @@ msgstr "" #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" "Sortierung nach einem von: uuid, human_readable_id, user_email, user, " "status, created, modified, buy_time, random. Präfix mit '-' für absteigend " @@ -421,8 +418,8 @@ msgstr "" #: core/docs/drf/viewsets.py:227 msgid "rewrite some fields of an existing order saving non-editables" msgstr "" -"Umschreiben einiger Felder einer bestehenden Kategorie, um nicht editierbare" -" Daten zu speichern" +"Umschreiben einiger Felder einer bestehenden Kategorie, um nicht editierbare " +"Daten zu speichern" #: core/docs/drf/viewsets.py:231 msgid "purchase an order" @@ -438,15 +435,14 @@ msgstr "" "wird der Kauf mit dem Guthaben des Benutzers abgeschlossen; bei Verwendung " "von \"force_payment\" wird eine Transaktion ausgelöst." -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "eine Bestellung kaufen, ohne ein Konto anzulegen" #: core/docs/drf/viewsets.py:246 msgid "finalizes the order purchase for a non-registered user." msgstr "" -"schließt den Kauf einer Bestellung für einen nicht registrierten Benutzer " -"ab." +"schließt den Kauf einer Bestellung für einen nicht registrierten Benutzer ab." #: core/docs/drf/viewsets.py:254 msgid "add product to order" @@ -463,8 +459,8 @@ msgstr "" #: core/docs/drf/viewsets.py:260 msgid "add a list of products to order, quantities will not count" msgstr "" -"Fügen Sie eine Liste der zu bestellenden Produkte hinzu, Mengen werden nicht" -" gezählt" +"Fügen Sie eine Liste der zu bestellenden Produkte hinzu, Mengen werden nicht " +"gezählt" #: core/docs/drf/viewsets.py:261 msgid "" @@ -533,8 +529,8 @@ msgstr "" #: core/docs/drf/viewsets.py:303 msgid "rewrite some fields of an existing wishlist saving non-editables" msgstr "" -"Umschreiben einiger Felder eines vorhandenen Attributs, um nicht editierbare" -" Daten zu speichern" +"Umschreiben einiger Felder eines vorhandenen Attributs, um nicht editierbare " +"Daten zu speichern" #: core/docs/drf/viewsets.py:307 msgid "add product to wishlist" @@ -581,18 +577,29 @@ msgstr "" msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "Filtern Sie nach einem oder mehreren Attributnamen/Wertpaaren. \n" "- **Syntax**: `attr_name=Methode-Wert[;attr2=Methode2-Wert2]...`\n" -"- **Methoden** (Standardwert ist \"icontains\", wenn nicht angegeben): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`\n" -"- **Wert-Typisierung**: JSON wird zuerst versucht (damit man Listen/Dicts übergeben kann), `true`/`false` für Booleans, Integers, Floats; ansonsten als String behandelt. \n" -"- Base64**: Präfix \"b64-\" für URL-sichere Base64-Kodierung des Rohwertes. \n" +"- **Methoden** (Standardwert ist \"icontains\", wenn nicht angegeben): " +"`iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, " +"`istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, " +"`gt`, `gte`, `in`\n" +"- **Wert-Typisierung**: JSON wird zuerst versucht (damit man Listen/Dicts " +"übergeben kann), `true`/`false` für Booleans, Integers, Floats; ansonsten " +"als String behandelt. \n" +"- Base64**: Präfix \"b64-\" für URL-sichere Base64-Kodierung des " +"Rohwertes. \n" "Beispiele: \n" "`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\", \"bluetooth\"]`,\n" "`b64-description=icontains-aGVhdC1jb2xk`" @@ -620,8 +627,7 @@ msgstr "(genau) Kategorie UUID" #: core/docs/drf/viewsets.py:378 msgid "(list) Tag names, case-insensitive" -msgstr "" -"(Liste) Tag-Namen, Groß- und Kleinschreibung wird nicht berücksichtigt" +msgstr "(Liste) Tag-Namen, Groß- und Kleinschreibung wird nicht berücksichtigt" #: core/docs/drf/viewsets.py:384 msgid "(gte) Minimum stock price" @@ -649,10 +655,12 @@ msgstr "(genau) Digital vs. physisch" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" -"Durch Kommata getrennte Liste der Felder, nach denen sortiert werden soll. Präfix mit \"-\" für absteigend. \n" +"Durch Kommata getrennte Liste der Felder, nach denen sortiert werden soll. " +"Präfix mit \"-\" für absteigend. \n" "**Erlaubt:** uuid, rating, name, slug, created, modified, price, random" #: core/docs/drf/viewsets.py:441 @@ -672,8 +680,8 @@ msgstr "Ein Produkt erstellen" #: core/docs/drf/viewsets.py:463 msgid "rewrite an existing product, preserving non-editable fields" msgstr "" -"Umschreiben eines bestehenden Produkts unter Beibehaltung nicht editierbarer" -" Felder" +"Umschreiben eines bestehenden Produkts unter Beibehaltung nicht editierbarer " +"Felder" #: core/docs/drf/viewsets.py:478 msgid "" @@ -721,10 +729,10 @@ msgstr "Autovervollständigung der Adresseingabe" #: core/docs/drf/viewsets.py:576 msgid "raw data query string, please append with data from geo-IP endpoint" msgstr "" -"docker compose exec app poetry run python manage.py deepl_translate -l en-gb" -" -l ar-ar -l cs-cz -l da-dk -l de-de -l en-us -l es-es -l fr-fr -l hi-in -l " -"it-it -l ja-jp -l kk-kz -l nl-nl -l pl -l pt-br -l ro-ro -l ru-ru -l zh-hans" -" -a core -a geo -a payments -a vibes_auth -a blog" +"docker compose exec app poetry run python manage.py deepl_translate -l en-gb " +"-l ar-ar -l cs-cz -l da-dk -l de-de -l en-us -l es-es -l fr-fr -l hi-in -l " +"it-it -l ja-jp -l kk-kz -l nl-nl -l pl -l pt-br -l ro-ro -l ru-ru -l zh-hans " +"-a core -a geo -a payments -a vibes_auth -a blog" #: core/docs/drf/viewsets.py:582 msgid "limit the results amount, 1 < limit < 10, default: 5" @@ -754,8 +762,8 @@ msgstr "" #: core/docs/drf/viewsets.py:615 msgid "rewrite some fields of an existing feedback saving non-editables" msgstr "" -"Umschreiben einiger Felder einer bestehenden Kategorie, um nicht editierbare" -" Daten zu speichern" +"Umschreiben einiger Felder einer bestehenden Kategorie, um nicht editierbare " +"Daten zu speichern" #: core/docs/drf/viewsets.py:622 msgid "list all order–product relations (simple view)" @@ -786,7 +794,7 @@ msgid "add or remove feedback on an order–product relation" msgstr "" "Feedback zu einer Bestellung-Produkt-Beziehung hinzufügen oder entfernen" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "Kein Suchbegriff angegeben." @@ -834,8 +842,8 @@ msgstr "Attribute" msgid "Quantity" msgstr "Menge" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "Schnecke" @@ -850,8 +858,8 @@ msgstr "Unterkategorien einbeziehen" #: core/filters.py:147 msgid "there must be a category_uuid to use include_subcategories flag" msgstr "" -"Es muss eine category_uuid vorhanden sein, um das Flag include_subcategories" -" zu verwenden" +"Es muss eine category_uuid vorhanden sein, um das Flag include_subcategories " +"zu verwenden" #: core/filters.py:280 msgid "Search (ID, product name or part number)" @@ -898,220 +906,243 @@ msgstr "Ebene" msgid "Product UUID" msgstr "Produkt UUID" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "Schlüssel, der im Cache zu suchen oder in den Cache zu legen ist" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "Im Cache zu speichernde Daten" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "Timeout in Sekunden, um die Daten in den Cache zu stellen" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "Zwischengespeicherte Daten" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "Camelized JSON-Daten aus der angeforderten URL" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "Nur URLs, die mit http(s):// beginnen, sind zulässig" -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "Ein Produkt zur Bestellung hinzufügen" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "Bestellung {order_uuid} nicht gefunden" +msgstr "Auftrag {order_uuid} nicht gefunden!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "Ein Produkt aus der Bestellung entfernen" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "Alle Produkte aus der Bestellung entfernen" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "Eine Bestellung kaufen" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "" "Bitte geben Sie entweder order_uuid oder order_hr_id an - beide schließen " "sich gegenseitig aus!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "Von der Methode order.buy() kam der falsche Typ: {type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "Eine Aktion für eine Liste von Produkten in der Bestellung ausführen" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "Entfernen/Hinzufügen" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "Aktion muss entweder \"Hinzufügen\" oder \"Entfernen\" sein!" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "Ausführen einer Aktion für eine Liste von Produkten in der Wunschliste" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "Bitte geben Sie den Wert `wishlist_uuid` an." + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "Wishlist {wishlist_uuid} nicht gefunden!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "Ein Produkt zur Bestellung hinzufügen" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "Wunschzettel {wishlist_uuid} nicht gefunden" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "Ein Produkt aus der Bestellung entfernen" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "Ein Produkt aus der Bestellung entfernen" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "Ein Produkt aus der Bestellung entfernen" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "Eine Bestellung kaufen" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" msgstr "" "Bitte senden Sie die Attribute als String im Format attr1=wert1,attr2=wert2" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "" +"Feedback zu einer Bestellung-Produkt-Beziehung hinzufügen oder entfernen" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "Aktion muss entweder `Add` oder `remove` sein!" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "Bestellprodukt {order_product_uuid} nicht gefunden!" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "Vom Benutzer angegebene Originaladresse" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} existiert nicht: {uuid}" +msgstr "{name} existiert nicht: {uuid}!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "Der Grenzwert muss zwischen 1 und 10 liegen." -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - funktioniert wie ein Zauber" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "Attribute" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "Gruppierte Attribute" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "Gruppen von Attributen" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "Kategorien" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "Marken" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "Kategorien" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "Markup Percentage" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "" "Welche Attribute und Werte können für die Filterung dieser Kategorie " "verwendet werden." -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." -msgstr "" -"Mindest- und Höchstpreise für Produkte in dieser Kategorie, sofern " -"verfügbar." - #: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." +msgstr "" +"Mindest- und Höchstpreise für Produkte in dieser Kategorie, sofern verfügbar." + +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "Tags für diese Kategorie" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "Produkte in dieser Kategorie" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "Anbieter" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "Breitengrad (Y-Koordinate)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "Längengrad (X-Koordinate)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "Wie" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "" "Bewertungswert von 1 bis einschließlich 10 oder 0, wenn nicht festgelegt." -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "Stellt das Feedback eines Benutzers dar." -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "Benachrichtigungen" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "Download-Url für dieses Bestellprodukt, falls zutreffend" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "Eine Liste der bestellten Produkte in dieser Reihenfolge" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "Rechnungsadresse" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" @@ -1119,746 +1150,740 @@ msgstr "" "Lieferadresse für diese Bestellung, leer lassen, wenn sie mit der " "Rechnungsadresse übereinstimmt oder nicht zutrifft" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "Gesamtpreis für diese Bestellung" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "Gesamtmenge der bestellten Produkte" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "Sind alle Produkte in der Bestellung digital" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "Vorgänge für diesen Auftrag" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "Bestellungen" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "Bild URL" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "Bilder des Produkts" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "Kategorie" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "Rückmeldungen" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "Marke" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "Attribut-Gruppen" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "Preis" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "Menge" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "Anzahl der Rückmeldungen" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "Produkte" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "Promocodes" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "Zum Verkauf stehende Produkte" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "Werbeaktionen" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "Anbieter" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "Produkt" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "Auf dem Wunschzettel stehende Produkte" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "Wunschzettel" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "Markierte Produkte" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "Produkt-Tags" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "Markierte Kategorien" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "Kategorien'-Tags" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "Name des Projekts" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "Unternehmen E-Mail" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "Name des Unternehmens" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "Adresse des Unternehmens" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "Telefonnummer des Unternehmens" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "" "E-Mail von\", muss manchmal anstelle des Host-Benutzerwerts verwendet werden" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "E-Mail-Host-Benutzer" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "Höchstbetrag für die Zahlung" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "Mindestbetrag für die Zahlung" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "Analytische Daten" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "Advertisement data" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "Konfiguration" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "Sprachcode" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "Name der Sprache" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "Sprachflagge, falls vorhanden :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "Eine Liste der unterstützten Sprachen abrufen" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "Suchergebnisse für Produkte" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "Suchergebnisse für Produkte" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "Elternteil dieser Gruppe" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "Übergeordnete Attributgruppe" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "Name der Attributgruppe" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "Attribut-Gruppe" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" "Speichert Anmeldeinformationen und Endpunkte, die für die API-Kommunikation " "des Anbieters erforderlich sind" -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "Informationen zur Authentifizierung" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "" "Definieren Sie den Aufschlag für Produkte, die von diesem Lieferanten " "bezogen werden" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "Prozentualer Aufschlag des Lieferanten" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "Name dieses Anbieters" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "Name des Anbieters" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "Interner Tag-Identifikator für das Produkt-Tag" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "Tag name" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "Benutzerfreundlicher Name für den Produktanhänger" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "Tag-Anzeigename" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "Produkt-Tag" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "Kategorie-Tag" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "Kategorie-Tags" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "Laden Sie ein Bild hoch, das diese Kategorie repräsentiert" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "Kategorie Bild" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "" "Definieren Sie einen prozentualen Aufschlag für Produkte in dieser Kategorie" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "" "Übergeordneter dieser Kategorie, um eine hierarchische Struktur zu bilden" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "Übergeordnete Kategorie" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "Name der Kategorie" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "Geben Sie einen Namen für diese Kategorie an" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "Fügen Sie eine detaillierte Beschreibung für diese Kategorie hinzu" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "Beschreibung der Kategorie" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "Tags, die helfen, diese Kategorie zu beschreiben oder zu gruppieren" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "Priorität" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "Name dieser Marke" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "Markenname" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "Laden Sie ein Logo hoch, das diese Marke repräsentiert" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "Marke kleines Bild" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "Laden Sie ein großes Logo hoch, das diese Marke repräsentiert" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "Großes Image der Marke" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "Fügen Sie eine detaillierte Beschreibung der Marke hinzu" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "Beschreibung der Marke" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "" "Optionale Kategorien, mit denen diese Marke in Verbindung gebracht wird" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "Kategorien" -#: core/models.py:330 +#: core/models.py:515 +msgid "the vendor supplying this product stock" +msgstr "Der Verkäufer, der dieses Produkt liefert, hat folgende Bestände" + +#: core/models.py:516 +msgid "associated vendor" +msgstr "Zugehöriger Anbieter" + +#: core/models.py:520 +msgid "final price to the customer after markups" +msgstr "Endpreis für den Kunden nach Aufschlägen" + +#: core/models.py:521 +msgid "selling price" +msgstr "Verkaufspreis" + +#: core/models.py:526 +msgid "the product associated with this stock entry" +msgstr "Das mit diesem Bestandseintrag verbundene Produkt" + +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "Zugehöriges Produkt" + +#: core/models.py:534 +msgid "the price paid to the vendor for this product" +msgstr "Der an den Verkäufer gezahlte Preis für dieses Produkt" + +#: core/models.py:535 +msgid "vendor purchase price" +msgstr "Einkaufspreis des Verkäufers" + +#: core/models.py:539 +msgid "available quantity of the product in stock" +msgstr "Verfügbare Menge des Produkts auf Lager" + +#: core/models.py:540 +msgid "quantity in stock" +msgstr "Vorrätige Menge" + +#: core/models.py:544 +msgid "vendor-assigned SKU for identifying the product" +msgstr "Vom Hersteller zugewiesene SKU zur Identifizierung des Produkts" + +#: core/models.py:545 +msgid "vendor sku" +msgstr "SKU des Verkäufers" + +#: core/models.py:551 +msgid "digital file associated with this stock if applicable" +msgstr "Digitale Datei, die mit diesem Bestand verbunden ist, falls zutreffend" + +#: core/models.py:552 +msgid "digital file" +msgstr "Digitale Datei" + +#: core/models.py:561 +msgid "stock entries" +msgstr "Bestandseinträge" + +#: core/models.py:605 msgid "category this product belongs to" msgstr "Kategorie, zu der dieses Produkt gehört" -#: core/models.py:339 +#: core/models.py:614 msgid "optionally associate this product with a brand" msgstr "Optional können Sie dieses Produkt mit einer Marke verknüpfen" -#: core/models.py:345 +#: core/models.py:620 msgid "tags that help describe or group this product" msgstr "Tags, die helfen, dieses Produkt zu beschreiben oder zu gruppieren" -#: core/models.py:350 +#: core/models.py:625 msgid "indicates whether this product is digitally delivered" msgstr "Gibt an, ob dieses Produkt digital geliefert wird" -#: core/models.py:351 +#: core/models.py:626 msgid "is product digital" msgstr "Ist das Produkt digital" -#: core/models.py:357 +#: core/models.py:632 msgid "provide a clear identifying name for the product" -msgstr "" -"Geben Sie einen eindeutigen Namen zur Identifizierung des Produkts an." +msgstr "Geben Sie einen eindeutigen Namen zur Identifizierung des Produkts an." -#: core/models.py:358 +#: core/models.py:633 msgid "product name" msgstr "Name des Produkts" -#: core/models.py:363 core/models.py:579 +#: core/models.py:638 core/models.py:955 msgid "add a detailed description of the product" msgstr "Fügen Sie eine detaillierte Beschreibung des Produkts hinzu" -#: core/models.py:364 +#: core/models.py:639 msgid "product description" msgstr "Beschreibung des Produkts" -#: core/models.py:371 +#: core/models.py:646 msgid "part number for this product" msgstr "Teilenummer für dieses Produkt" -#: core/models.py:372 +#: core/models.py:647 msgid "part number" msgstr "Teilnummer" -#: core/models.py:451 +#: core/models.py:753 msgid "category of this attribute" msgstr "Kategorie dieses Attributs" -#: core/models.py:459 +#: core/models.py:761 msgid "group of this attribute" msgstr "Gruppe dieses Attributs" -#: core/models.py:465 +#: core/models.py:767 msgid "string" msgstr "Zeichenfolge" -#: core/models.py:466 +#: core/models.py:768 msgid "integer" msgstr "Integer" -#: core/models.py:467 +#: core/models.py:769 msgid "float" msgstr "Schwimmer" -#: core/models.py:468 +#: core/models.py:770 msgid "boolean" msgstr "Boolesche" -#: core/models.py:469 +#: core/models.py:771 msgid "array" msgstr "Array" -#: core/models.py:470 +#: core/models.py:772 msgid "object" msgstr "Objekt" -#: core/models.py:472 +#: core/models.py:774 msgid "type of the attribute's value" msgstr "Typ des Attributwerts" -#: core/models.py:473 +#: core/models.py:775 msgid "value type" msgstr "Werttyp" -#: core/models.py:478 +#: core/models.py:780 msgid "name of this attribute" msgstr "Name dieses Attributs" -#: core/models.py:479 +#: core/models.py:781 msgid "attribute's name" msgstr "Name des Attributs" -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 msgid "attribute" msgstr "Attribut" -#: core/models.py:498 +#: core/models.py:823 msgid "attribute of this value" msgstr "Attribut dieses Wertes" -#: core/models.py:506 +#: core/models.py:831 msgid "the specific product associated with this attribute's value" msgstr "" "Das spezifische Produkt, das mit dem Wert dieses Attributs verbunden ist" -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 -msgid "associated product" -msgstr "Zugehöriges Produkt" - -#: core/models.py:512 +#: core/models.py:837 msgid "the specific value for this attribute" msgstr "Der spezifische Wert für dieses Attribut" -#: core/models.py:528 +#: core/models.py:871 msgid "provide alternative text for the image for accessibility" msgstr "" "Geben Sie einen alternativen Text für das Bild an, um die Barrierefreiheit " "zu gewährleisten." -#: core/models.py:529 +#: core/models.py:872 msgid "image alt text" msgstr "Bild-Alt-Text" -#: core/models.py:532 +#: core/models.py:875 msgid "upload the image file for this product" msgstr "Laden Sie die Bilddatei für dieses Produkt hoch" -#: core/models.py:533 core/models.py:558 +#: core/models.py:876 core/models.py:901 msgid "product image" msgstr "Produktbild" -#: core/models.py:539 +#: core/models.py:882 msgid "determines the order in which images are displayed" msgstr "Legt die Reihenfolge fest, in der die Bilder angezeigt werden" -#: core/models.py:540 +#: core/models.py:883 msgid "display priority" msgstr "Priorität anzeigen" -#: core/models.py:545 +#: core/models.py:888 msgid "the product that this image represents" msgstr "Das Produkt, das dieses Bild darstellt" -#: core/models.py:559 +#: core/models.py:902 msgid "product images" msgstr "Produktbilder" -#: core/models.py:567 +#: core/models.py:943 msgid "percentage discount for the selected products" msgstr "Prozentualer Rabatt für die ausgewählten Produkte" -#: core/models.py:568 +#: core/models.py:944 msgid "discount percentage" msgstr "Prozentsatz der Ermäßigung" -#: core/models.py:573 +#: core/models.py:949 msgid "provide a unique name for this promotion" msgstr "Geben Sie einen eindeutigen Namen für diese Aktion an" -#: core/models.py:574 +#: core/models.py:950 msgid "promotion name" msgstr "Name der Aktion" -#: core/models.py:580 +#: core/models.py:956 msgid "promotion description" msgstr "Promotion description" -#: core/models.py:585 +#: core/models.py:961 msgid "select which products are included in this promotion" msgstr "Wählen Sie aus, welche Produkte in dieser Aktion enthalten sind" -#: core/models.py:586 +#: core/models.py:962 msgid "included products" msgstr "Enthaltene Produkte" -#: core/models.py:590 +#: core/models.py:966 msgid "promotion" msgstr "Förderung" -#: core/models.py:605 -msgid "the vendor supplying this product stock" -msgstr "Der Verkäufer, der dieses Produkt liefert, hat folgende Bestände" - -#: core/models.py:606 -msgid "associated vendor" -msgstr "Zugehöriger Anbieter" - -#: core/models.py:610 -msgid "final price to the customer after markups" -msgstr "Endpreis für den Kunden nach Aufschlägen" - -#: core/models.py:611 -msgid "selling price" -msgstr "Verkaufspreis" - -#: core/models.py:616 -msgid "the product associated with this stock entry" -msgstr "Das mit diesem Bestandseintrag verbundene Produkt" - -#: core/models.py:624 -msgid "the price paid to the vendor for this product" -msgstr "Der an den Verkäufer gezahlte Preis für dieses Produkt" - -#: core/models.py:625 -msgid "vendor purchase price" -msgstr "Einkaufspreis des Verkäufers" - -#: core/models.py:629 -msgid "available quantity of the product in stock" -msgstr "Verfügbare Menge des Produkts auf Lager" - -#: core/models.py:630 -msgid "quantity in stock" -msgstr "Vorrätige Menge" - -#: core/models.py:634 -msgid "vendor-assigned SKU for identifying the product" -msgstr "Vom Hersteller zugewiesene SKU zur Identifizierung des Produkts" - -#: core/models.py:635 -msgid "vendor sku" -msgstr "SKU des Verkäufers" - -#: core/models.py:641 -msgid "digital file associated with this stock if applicable" -msgstr "" -"Digitale Datei, die mit diesem Bestand verbunden ist, falls zutreffend" - -#: core/models.py:642 -msgid "digital file" -msgstr "Digitale Datei" - -#: core/models.py:651 -msgid "stock entries" -msgstr "Bestandseinträge" - -#: core/models.py:660 +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "Produkte, die der Benutzer als gewünscht markiert hat" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "Benutzer, dem diese Wunschliste gehört" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "Besitzer der Wishlist" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "Wunschzettel" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} existiert nicht: {product_uuid}" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "Dokumentarfilm" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "Dokumentarfilme" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "Ungelöst" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "Adresszeile für den Kunden" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "Adresszeile" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "Straße" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "Bezirk" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "Stadt" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "Region" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "Postleitzahl" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "Land" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "Geolocation Point(Längengrad, Breitengrad)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "Vollständige JSON-Antwort vom Geocoder für diese Adresse" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "Gespeicherte JSON-Antwort vom Geokodierungsdienst" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "Adresse" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "Adressen" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "" "Einzigartiger Code, den ein Nutzer zum Einlösen eines Rabatts verwendet" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "Kennung des Promo-Codes" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "" -"Fester Rabattbetrag, der angewandt wird, wenn kein Prozentsatz verwendet " -"wird" +"Fester Rabattbetrag, der angewandt wird, wenn kein Prozentsatz verwendet wird" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "Fester Rabattbetrag" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "Prozentualer Rabatt, wenn der Festbetrag nicht verwendet wird" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "Prozentualer Rabatt" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "Zeitstempel, wann der Promocode abläuft" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "Ende der Gültigkeitsdauer" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "Zeitstempel, ab dem dieser Promocode gültig ist" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "Beginn der Gültigkeitsdauer" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "" "Zeitstempel, wann der Promocode verwendet wurde, leer, wenn noch nicht " "verwendet" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "Zeitstempel der Verwendung" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "Diesem Promocode zugewiesener Benutzer, falls zutreffend" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "Zugewiesener Benutzer" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "Promo-Code" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "Promo-Codes" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." @@ -1866,142 +1891,152 @@ msgstr "" "Es sollte nur eine Art von Rabatt definiert werden (Betrag oder " "Prozentsatz), aber nicht beides oder keines von beiden." -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "Promocode wurde bereits verwendet" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "Ungültiger Rabatttyp für Promocode {self.uuid}" +msgstr "Ungültiger Rabatttyp für den Promocode {self.uuid}!" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "Die für diese Bestellung verwendete Rechnungsadresse" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "Optionaler Promo-Code für diese Bestellung" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "Angewandter Promo-Code" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "Die für diese Bestellung verwendete Lieferadresse" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "Lieferadresse" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "Aktueller Status des Auftrags in seinem Lebenszyklus" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "Status der Bestellung" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" "JSON-Struktur der Benachrichtigungen, die den Benutzern angezeigt werden " "sollen; in der Admin-UI wird die Tabellenansicht verwendet" -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "JSON-Darstellung der Auftragsattribute für diesen Auftrag" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "Der Benutzer, der die Bestellung aufgegeben hat" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "Benutzer" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "Der Zeitstempel, zu dem der Auftrag abgeschlossen wurde" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "Zeit kaufen" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "Ein von Menschen lesbarer Identifikator für den Auftrag" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "menschenlesbare ID" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "Bestellung" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "Ein Benutzer darf immer nur einen schwebenden Auftrag haben!" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "" "Sie können keine Produkte zu einem Auftrag hinzufügen, der nicht in " "Bearbeitung ist." -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "Sie können keine inaktiven Produkte zur Bestellung hinzufügen" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "Sie können nicht mehr Produkte hinzufügen, als auf Lager sind" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "" "Sie können keine Produkte aus einer Bestellung entfernen, die nicht in " "Bearbeitung ist." -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "{name} existiert nicht mit Abfrage <{query}>" +msgstr "{name} existiert nicht mit Abfrage <{query}>!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "Promocode existiert nicht" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "" "Sie können nur physische Produkte mit angegebener Lieferadresse kaufen!" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "Adresse ist nicht vorhanden" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "" "Sie können im Moment nicht kaufen, bitte versuchen Sie es in ein paar " "Minuten erneut." -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "Ungültiger Force-Wert" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "Sie können keine leere Bestellung kaufen!" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "" +"Sie können keine Produkte aus einer Bestellung entfernen, die nicht in " +"Bearbeitung ist." + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "Ein Benutzer ohne Guthaben kann nicht mit Guthaben kaufen!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "Unzureichende Mittel für die Ausführung des Auftrags" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" @@ -2009,124 +2044,127 @@ msgstr "" "Sie können nicht ohne Registrierung kaufen, bitte geben Sie die folgenden " "Informationen an: Kundenname, Kunden-E-Mail, Kunden-Telefonnummer" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" msgstr "" "Ungültige Zahlungsmethode: {payment_method} von {available_payment_methods}!" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "" "Der Preis, den der Kunde zum Zeitpunkt des Kaufs für dieses Produkt bezahlt " "hat" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "Einkaufspreis zum Zeitpunkt der Bestellung" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "Interne Kommentare für Administratoren zu diesem bestellten Produkt" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "Interne Kommentare" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "Benutzerbenachrichtigungen" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "JSON-Darstellung der Attribute dieses Artikels" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "Bestellte Produktattribute" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "Verweis auf den übergeordneten Auftrag, der dieses Produkt enthält" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "Übergeordneter Auftrag" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "Das spezifische Produkt, das mit dieser Auftragszeile verbunden ist" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "Menge dieses spezifischen Produkts in der Bestellung" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "Produktmenge" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "Aktueller Status dieses Produkts im Auftrag" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "Status der Produktlinie" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "Das Bestellprodukt muss eine zugehörige Bestellung haben!" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "falsche Aktion für die Rückmeldung angegeben: {action}" +msgstr "Falsche Aktion für Feedback angegeben: {action}!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "" "Sie können keine Produkte aus einer Bestellung entfernen, die nicht in " "Bearbeitung ist." -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "Herunterladen" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "Herunterladen" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "" "Sie können kein digitales Asset für eine nicht abgeschlossene Bestellung " "herunterladen" -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "Kommentare der Nutzer über ihre Erfahrungen mit dem Produkt" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "Kommentare zum Feedback" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "" -"Verweist auf das spezifische Produkt in einer Bestellung, auf das sich diese" -" Rückmeldung bezieht" +"Verweist auf das spezifische Produkt in einer Bestellung, auf das sich diese " +"Rückmeldung bezieht" -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "Produkt zur Bestellung" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "Vom Benutzer zugewiesene Bewertung für das Produkt" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "Produktbewertung" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "Rückmeldung" @@ -2137,13 +2175,13 @@ msgstr "" "Sie müssen einen Kommentar, eine Bewertung und eine Produktnummer angeben, " "um eine Bewertung abzugeben." -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "Fehler bei der Erstellung des Promocodes: {e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2152,7 +2190,7 @@ msgid "order confirmation" msgstr "Bestätigung der Bestellung" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2169,7 +2207,8 @@ msgstr "Hallo %(order.user.first_name)s," #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" msgstr "" "Vielen Dank für Ihre Bestellung #%(order.pk)s! Wir freuen uns, Ihnen " @@ -2177,14 +2216,14 @@ msgstr "" "Nachfolgend finden Sie die Details Ihrer Bestellung:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "Insgesamt" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2204,23 +2243,23 @@ msgstr "" #: core/templates/digital_order_created_email.html:133 #, python-format msgid "best regards,
the %(config.PROJECT_NAME)s team" -msgstr "Mit freundlichen Grüßen,
das %(config.PROJECT_NAME)s Team" +msgstr "Mit freundlichen Grüßen,
das %(config.PROJECT_NAME)s-Team" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "Alle Rechte vorbehalten" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "Bestellung Geliefert" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "Hallo %(user_first_name)s," -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" @@ -2229,7 +2268,7 @@ msgstr "" "Wir haben Ihre Bestellung erfolgreich bearbeitet №%(order_uuid)s! " "Nachstehend finden Sie die Details Ihrer Bestellung:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2237,12 +2276,12 @@ msgstr "" "zusätzliche\n" " Informationen" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "Wert" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -2251,10 +2290,10 @@ msgstr "" "Wenn Sie Fragen haben, wenden Sie sich bitte an unseren Support unter " "%(contact_email)s." -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Mit freundlichen Grüßen,
das %(project_name)s Team" +msgstr "Mit freundlichen Grüßen,
das %(project_name)s-Team" #: core/templates/json_table_widget.html:5 msgid "key" @@ -2263,7 +2302,8 @@ msgstr "Schlüssel" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" msgstr "" "Vielen Dank für Ihre Bestellung! Wir freuen uns, Ihren Kauf zu bestätigen. " @@ -2283,7 +2323,7 @@ msgstr "Ihre Bestellung wird an die folgende Adresse geliefert:" #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "Mit freundlichen Grüßen,
das %(config.PROJECT_NAME)s Team" +msgstr "Mit freundlichen Grüßen,
Das %(config.PROJECT_NAME)s-Team" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2300,33 +2340,22 @@ msgstr "Sowohl Daten als auch Timeout sind erforderlich" #: core/utils/caching.py:43 msgid "invalid timeout value, it must be between 0 and 216000 seconds" -msgstr "" -"Ungültiger Timeout-Wert, er muss zwischen 0 und 216000 Sekunden liegen" - -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model} muss Modell sein" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data} muss ein Listenobjekt sein" +msgstr "Ungültiger Timeout-Wert, er muss zwischen 0 und 216000 Sekunden liegen" #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | Kontakt initiiert" +msgstr "{config.PROJECT_NAME} | Kontakt eingeleitet" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" msgstr "{config.PROJECT_NAME} | Auftragsbestätigung" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" -msgstr "{config.PROJECT_NAME} | Auftrag ausgeliefert" +msgstr "{config.PROJECT_NAME} | Bestellung ausgeliefert" #: core/utils/messages.py:3 msgid "you do not have permission to perform this action." @@ -2347,15 +2376,15 @@ msgstr "" msgid "invalid phone number format" msgstr "Ungültiges Rufnummernformat" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "Sie können das digitale Asset nur einmal herunterladen" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "Favicon nicht gefunden" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" -msgstr "Geokodierungsfehler: {e}" +msgstr "Geocodierungsfehler: {e}" diff --git a/core/locale/en_GB/LC_MESSAGES/django.mo b/core/locale/en_GB/LC_MESSAGES/django.mo index 5b92c417..ad23a4ca 100644 Binary files a/core/locale/en_GB/LC_MESSAGES/django.mo and b/core/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/core/locale/en_GB/LC_MESSAGES/django.po b/core/locale/en_GB/LC_MESSAGES/django.po index f745b8ec..fde33fa9 100644 --- a/core/locale/en_GB/LC_MESSAGES/django.po +++ b/core/locale/en_GB/LC_MESSAGES/django.po @@ -5,9 +5,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -17,118 +17,116 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "Unique ID" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "Unique ID is used to surely identify any database object" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "Is Active" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" "if set to false, this object can't be seen by users without needed permission" msgstr "" "If set to false, this object can't be seen by users without needed permission" -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "Created" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "When the object first appeared on the database" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "Modified" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "When the object was last edited" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "Translations" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "General" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "Relations" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "Metadata" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "Timestamps" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" msgstr "Activate selected %(verbose_name_plural)s" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)s activated successfully!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "Selected items have been activated!" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" msgstr "Deactivate selected %(verbose_name_plural)s" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "%(verbose_name_plural)s deactivated successfully." +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "Selected items have been deactivated!" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "Attribute Value" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "Attribute Values" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "Image" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "Images" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "Stock" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "Stocks" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "Order Product" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "Order Products" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "Children" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "Config" @@ -180,7 +178,7 @@ msgstr "Momental" msgid "successful" msgstr "Successful" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "Cache I/O" @@ -204,7 +202,7 @@ msgstr "Get application's exposable parameters" msgid "send a message to the support team" msgstr "Send a message to the support team" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "Request a CORSed URL. Only https allowed." @@ -414,7 +412,7 @@ msgstr "" "completed using the user's balance; If `force_payment` is used, a " "transaction is initiated." -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "purchase an order without account creation" @@ -744,7 +742,7 @@ msgstr "delete an order–product relation" msgid "add or remove feedback on an order–product relation" msgstr "add or remove feedback on an order–product relation" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "No search term provided." @@ -792,8 +790,8 @@ msgstr "Attributes" msgid "Quantity" msgstr "Quantity" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 core/models.py:307 -#: core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "Slug" @@ -854,100 +852,109 @@ msgstr "Level" msgid "Product UUID" msgstr "Product UUID" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "Key to look for in or set into the cache" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "Data to store in cache" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "Timeout in seconds to set the data for into the cache" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "Cached data" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "Camelized JSON data from the requested URL" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "Only URLs starting with http(s):// are allowed" -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "Add a product to the order" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "Order {order_uuid} not found" +msgstr "Order {order_uuid} not found!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "Remove a product from the order" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "Remove all products from the order" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "Buy an order" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "Please provide either order_uuid or order_hr_id - mutually exclusive!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "Wrong type came from order.buy() method: {type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "Perform an action on a list of products in the order" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "Remove/Add" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "Action must be either \"add\" or \"remove\"!" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "Perform an action on a list of products in the wishlist" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "Please provide `wishlist_uuid` value." + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "Wishlist {wishlist_uuid} not found!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "Add a product to the order" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "Wishlist {wishlist_uuid} not found" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "Remove a product from the order" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "Remove a product from the order" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "Remove a product from the order" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "Buy an order" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" "please send the attributes as the string formatted like attr1=value1," "attr2=value2" @@ -955,113 +962,128 @@ msgstr "" "Please send the attributes as the string formatted like attr1=value1," "attr2=value2" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "Add or delete a feedback for the orderproduct" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "Action must be either `add` or `remove`!" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "Orderproduct {order_product_uuid} not found!" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "Original address string provided by the user" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} does not exist: {uuid}" +msgstr "{name} does not exist: {uuid}!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "Limit must be between 1 and 10" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - works like a charm" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "Attributes" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "Grouped attributes" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "Groups of attributes" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "Categories" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "Brands" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "Categories" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "Markup Percentage" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "Which attributes and values can be used for filtering this category." -#: core/graphene/object_types.py:133 +#: core/graphene/object_types.py:135 msgid "minimum and maximum prices for products in this category, if available." msgstr "" "Minimum and maximum prices for products in this category, if available." -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "Tags for this category" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "Products in this category" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "Vendors" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "Latitude (Y coordinate)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "Longitude (X coordinate)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "Comment" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "Rating value from 1 to 10, inclusive, or 0 if not set." -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "Represents feedback from a user." -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "Notifications" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "Download url for this order product if applicable" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "A list of order products in this order" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "Billing address" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" @@ -1069,728 +1091,726 @@ msgstr "" "Shipping address for this order, leave blank if same as billing address or " "if not applicable" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "Total price of this order" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "Total quantity of products in order" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "Are all of the products in the order digital" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "Transactions for this order" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "Orders" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "Image URL" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "Product's images" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "Category" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "Feedbacks" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "Brand" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "Attribute groups" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "Price" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "Quantity" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "Number of feedbacks" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "Products" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "Promocodes" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "Products on sale" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "Promotions" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "Vendor" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "Product" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "Wishlisted products" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "Wishlists" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "Tagged products" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "Product tags" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "Tagged categories" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "Categories' tags" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "Project name" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "Company Email" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "Company Name" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "Company Address" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "Company Phone Number" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "'email from', sometimes it must be used instead of host user value" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "Email host user" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "Maximum amount for payment" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "Minimum amount for payment" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "Analytics data" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "Advertisement data" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "Configuration" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "Language code" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "Language name" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "Language flag, if exists :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "Get a list of supported languages" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "Products search results" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "Products search results" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "Parent of this group" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "Parent attribute group" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "Attribute group's name" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "Attribute group" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" "Stores credentials and endpoints required for vendor's API communication" -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "Authentication info" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "Define the markup for products retrieved from this vendor" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "Vendor markup percentage" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "Name of this vendor" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "Vendor name" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "Internal tag identifier for the product tag" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "Tag name" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "User-friendly name for the product tag" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "Tag display name" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "Product tag" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "category tag" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "category tags" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "Upload an image representing this category" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "Category image" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "Define a markup percentage for products in this category" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "Parent of this category to form a hierarchical structure" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "Parent category" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "Category name" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "Provide a name for this category" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "Add a detailed description for this category" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "Category description" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "tags that help describe or group this category" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "Priority" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "Name of this brand" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "Brand name" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "Upload a logo representing this brand" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "Brand small image" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "Upload a big logo representing this brand" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "Brand big image" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "Add a detailed description of the brand" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "Brand description" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "Optional categories that this brand is associated with" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "Categories" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "Category this product belongs to" - -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "Optionally associate this product with a brand" - -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "Tags that help describe or group this product" - -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "Indicates whether this product is digitally delivered" - -#: core/models.py:351 -msgid "is product digital" -msgstr "Is product digital" - -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "Provide a clear identifying name for the product" - -#: core/models.py:358 -msgid "product name" -msgstr "Product name" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "Add a detailed description of the product" - -#: core/models.py:364 -msgid "product description" -msgstr "Product description" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "Part number for this product" - -#: core/models.py:372 -msgid "part number" -msgstr "Part number" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "Category of this attribute" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "Group of this attribute" - -#: core/models.py:465 -msgid "string" -msgstr "String" - -#: core/models.py:466 -msgid "integer" -msgstr "Integer" - -#: core/models.py:467 -msgid "float" -msgstr "Float" - -#: core/models.py:468 -msgid "boolean" -msgstr "Boolean" - -#: core/models.py:469 -msgid "array" -msgstr "Array" - -#: core/models.py:470 -msgid "object" -msgstr "Object" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "Type of the attribute's value" - -#: core/models.py:473 -msgid "value type" -msgstr "Value type" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "Name of this attribute" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "Attribute's name" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "Attribute" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "Attribute of this value" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "The specific product associated with this attribute's value" - -#: core/models.py:507 core/models.py:546 core/models.py:617 core/models.py:1361 -msgid "associated product" -msgstr "Associated product" - -#: core/models.py:512 -msgid "the specific value for this attribute" -msgstr "The specific value for this attribute" - -#: core/models.py:528 -msgid "provide alternative text for the image for accessibility" -msgstr "Provide alternative text for the image for accessibility" - -#: core/models.py:529 -msgid "image alt text" -msgstr "Image alt text" - -#: core/models.py:532 -msgid "upload the image file for this product" -msgstr "Upload the image file for this product" - -#: core/models.py:533 core/models.py:558 -msgid "product image" -msgstr "Product image" - -#: core/models.py:539 -msgid "determines the order in which images are displayed" -msgstr "Determines the order in which images are displayed" - -#: core/models.py:540 -msgid "display priority" -msgstr "Display priority" - -#: core/models.py:545 -msgid "the product that this image represents" -msgstr "The product that this image represents" - -#: core/models.py:559 -msgid "product images" -msgstr "Product images" - -#: core/models.py:567 -msgid "percentage discount for the selected products" -msgstr "Percentage discount for the selected products" - -#: core/models.py:568 -msgid "discount percentage" -msgstr "Discount percentage" - -#: core/models.py:573 -msgid "provide a unique name for this promotion" -msgstr "Provide a unique name for this promotion" - -#: core/models.py:574 -msgid "promotion name" -msgstr "Promotion name" - -#: core/models.py:580 -msgid "promotion description" -msgstr "Promotion description" - -#: core/models.py:585 -msgid "select which products are included in this promotion" -msgstr "Select which products are included in this promotion" - -#: core/models.py:586 -msgid "included products" -msgstr "Included products" - -#: core/models.py:590 -msgid "promotion" -msgstr "Promotion" - -#: core/models.py:605 +#: core/models.py:515 msgid "the vendor supplying this product stock" msgstr "The vendor supplying this product stock" -#: core/models.py:606 +#: core/models.py:516 msgid "associated vendor" msgstr "Associated vendor" -#: core/models.py:610 +#: core/models.py:520 msgid "final price to the customer after markups" msgstr "Final price to the customer after markups" -#: core/models.py:611 +#: core/models.py:521 msgid "selling price" msgstr "Selling price" -#: core/models.py:616 +#: core/models.py:526 msgid "the product associated with this stock entry" msgstr "The product associated with this stock entry" -#: core/models.py:624 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "Associated product" + +#: core/models.py:534 msgid "the price paid to the vendor for this product" msgstr "The price paid to the vendor for this product" -#: core/models.py:625 +#: core/models.py:535 msgid "vendor purchase price" msgstr "Vendor purchase price" -#: core/models.py:629 +#: core/models.py:539 msgid "available quantity of the product in stock" msgstr "Available quantity of the product in stock" -#: core/models.py:630 +#: core/models.py:540 msgid "quantity in stock" msgstr "Quantity in stock" -#: core/models.py:634 +#: core/models.py:544 msgid "vendor-assigned SKU for identifying the product" msgstr "Vendor-assigned SKU for identifying the product" -#: core/models.py:635 +#: core/models.py:545 msgid "vendor sku" msgstr "Vendor's SKU" -#: core/models.py:641 +#: core/models.py:551 msgid "digital file associated with this stock if applicable" msgstr "Digital file associated with this stock if applicable" -#: core/models.py:642 +#: core/models.py:552 msgid "digital file" msgstr "Digital file" -#: core/models.py:651 +#: core/models.py:561 msgid "stock entries" msgstr "Stock entries" -#: core/models.py:660 +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "Category this product belongs to" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "Optionally associate this product with a brand" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "Tags that help describe or group this product" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "Indicates whether this product is digitally delivered" + +#: core/models.py:626 +msgid "is product digital" +msgstr "Is product digital" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "Provide a clear identifying name for the product" + +#: core/models.py:633 +msgid "product name" +msgstr "Product name" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "Add a detailed description of the product" + +#: core/models.py:639 +msgid "product description" +msgstr "Product description" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "Part number for this product" + +#: core/models.py:647 +msgid "part number" +msgstr "Part number" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "Category of this attribute" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "Group of this attribute" + +#: core/models.py:767 +msgid "string" +msgstr "String" + +#: core/models.py:768 +msgid "integer" +msgstr "Integer" + +#: core/models.py:769 +msgid "float" +msgstr "Float" + +#: core/models.py:770 +msgid "boolean" +msgstr "Boolean" + +#: core/models.py:771 +msgid "array" +msgstr "Array" + +#: core/models.py:772 +msgid "object" +msgstr "Object" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "Type of the attribute's value" + +#: core/models.py:775 +msgid "value type" +msgstr "Value type" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "Name of this attribute" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "Attribute's name" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "Attribute" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "Attribute of this value" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "The specific product associated with this attribute's value" + +#: core/models.py:837 +msgid "the specific value for this attribute" +msgstr "The specific value for this attribute" + +#: core/models.py:871 +msgid "provide alternative text for the image for accessibility" +msgstr "Provide alternative text for the image for accessibility" + +#: core/models.py:872 +msgid "image alt text" +msgstr "Image alt text" + +#: core/models.py:875 +msgid "upload the image file for this product" +msgstr "Upload the image file for this product" + +#: core/models.py:876 core/models.py:901 +msgid "product image" +msgstr "Product image" + +#: core/models.py:882 +msgid "determines the order in which images are displayed" +msgstr "Determines the order in which images are displayed" + +#: core/models.py:883 +msgid "display priority" +msgstr "Display priority" + +#: core/models.py:888 +msgid "the product that this image represents" +msgstr "The product that this image represents" + +#: core/models.py:902 +msgid "product images" +msgstr "Product images" + +#: core/models.py:943 +msgid "percentage discount for the selected products" +msgstr "Percentage discount for the selected products" + +#: core/models.py:944 +msgid "discount percentage" +msgstr "Discount percentage" + +#: core/models.py:949 +msgid "provide a unique name for this promotion" +msgstr "Provide a unique name for this promotion" + +#: core/models.py:950 +msgid "promotion name" +msgstr "Promotion name" + +#: core/models.py:956 +msgid "promotion description" +msgstr "Promotion description" + +#: core/models.py:961 +msgid "select which products are included in this promotion" +msgstr "Select which products are included in this promotion" + +#: core/models.py:962 +msgid "included products" +msgstr "Included products" + +#: core/models.py:966 +msgid "promotion" +msgstr "Promotion" + +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "Products that the user has marked as wanted" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "User who owns this wishlist" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "Wishlist's Owner" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "Wishlist" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} does not exist: {product_uuid}" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "Documentary" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "Documentaries" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "Unresolved" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "Address line for the customer" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "Address line" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "Street" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "District" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "City" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "Region" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "Postal code" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "Country" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "Geolocation Point(Longitude, Latitude)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "Full JSON response from geocoder for this address" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "Stored JSON response from the geocoding service" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "Address" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "Adresses" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "Unique code used by a user to redeem a discount" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "Promo code identifier" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "Fixed discount amount applied if percent is not used" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "Fixed discount amount" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "Percentage discount applied if fixed amount is not used" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "Percentage discount" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "Timestamp when the promocode expires" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "End validity time" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "Timestamp from which this promocode is valid" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "Start validity time" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "Timestamp when the promocode was used, blank if not used yet" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "Usage timestamp" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "User assigned to this promocode if applicable" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "Assigned user" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "Promo code" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "Promo codes" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." @@ -1798,136 +1818,144 @@ msgstr "" "Only one type of discount should be defined (amount or percent), but not " "both or neither." -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "Promocode has been used already" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "Invalid discount type for promocode {self.uuid}" +msgstr "Invalid discount type for promocode {self.uuid}!" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "The billing address used for this order" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "Optional promo code applied to this order" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "Applied promo code" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "The shipping address used for this order" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "Shipping address" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "Current status of the order in its lifecycle" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "Order status" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" "JSON structure of notifications to display to users, in admin UI the table-" "view is used" -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "JSON representation of order attributes for this order" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "The user who placed the order" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "User" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "The timestamp when the order was finalized" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "Buy time" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "A human-readable identifier for the order" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "human-readable ID" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "Order" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "A user must have only one pending order at a time!" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "You cannot add products to an order that is not a pending one" -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "You cannot add inactive products to order" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "You cannot add more products than available in stock" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "You cannot remove products from an order that is not a pending one" -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "{name} does not exist with query <{query}>" +msgstr "{name} does not exist with query <{query}>!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "Promocode does not exist" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "You can only buy physical products with shipping address specified!" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "Address does not exist" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "" "You can not purchase at this moment, please try again in a few minutes." -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "Invalid force value" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "You cannot purchase an empty order!" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "You cannot buy an order without a user!" + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "A user without a balance cannot buy with balance!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "Insufficient funds to complete the order" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" @@ -1935,116 +1963,120 @@ msgstr "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" msgstr "" "Invalid payment method: {payment_method} from {available_payment_methods}!" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "The price paid by the customer for this product at purchase time" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "Purchase price at order time" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "Internal comments for admins about this ordered product" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "Internal comments" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "User notifications" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "JSON representation of this item's attributes" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "Ordered product attributes" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "Reference to the parent order that contains this product" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "Parent order" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "The specific product associated with this order line" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "Quantity of this specific product in the order" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "Product quantity" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "Current status of this product in the order" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "Product line status" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "Orderproduct must have an associated order!" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "wrong action specified for feedback: {action}" +msgstr "Wrong action specified for feedback: {action}!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "you cannot feedback an order which is not received" -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "Download" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "Downloads" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "You can not download a digital asset for a non-finished order" -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "User-provided comments about their experience with the product" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "Feedback comments" -#: core/models.py:1490 +#: core/models.py:1970 msgid "references the specific product in an order that this feedback is about" msgstr "" "References the specific product in an order that this feedback is about" -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "Related order product" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "User-assigned rating for the product" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "Product rating" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "Feedback" @@ -2054,13 +2086,13 @@ msgid "" msgstr "" "you must provide a comment, rating, and order product uuid to add feedback." -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "Error during promocode creation: {e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2069,7 +2101,7 @@ msgid "order confirmation" msgstr "Order Confirmation" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2094,14 +2126,14 @@ msgstr "" "have taken your order into work. Below are the details of your order:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "Total" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2124,20 +2156,20 @@ msgid "best regards,
the %(config.PROJECT_NAME)s team" msgstr "Best regards,
the %(config.PROJECT_NAME)s team" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "All rights reserved" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "Order Delivered" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "Hello %(user_first_name)s," -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" @@ -2146,7 +2178,7 @@ msgstr "" "We have successfully processed your order №%(order_uuid)s! Below are the " "details of your order:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2154,12 +2186,12 @@ msgstr "" "additional\n" " information" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "Value" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -2168,7 +2200,7 @@ msgstr "" "If you have any questions, feel free to contact our support at " "%(contact_email)s." -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Best regards,
the %(project_name)s team" @@ -2201,7 +2233,7 @@ msgstr "Your order will be delivered to the following address:" #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "Best regards,
the %(config.PROJECT_NAME)s team" +msgstr "Best regards,
The %(config.PROJECT_NAME)s team" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2220,27 +2252,17 @@ msgstr "Both data and timeout are required" msgid "invalid timeout value, it must be between 0 and 216000 seconds" msgstr "Invalid timeout value, it must be between 0 and 216000 seconds" -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model} must be model" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data} must be list object" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | Contact Us initiated" +msgstr "{config.PROJECT_NAME} | contact us initiated" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" msgstr "{config.PROJECT_NAME} | Order Confirmation" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" msgstr "{config.PROJECT_NAME} | Order Delivered" @@ -2256,45 +2278,22 @@ msgstr "NOMINATIM_URL parameter must be configured!" #: core/validators.py:16 #, python-brace-format msgid "image dimensions should not exceed w{max_width} x h{max_height} pixels" -msgstr "Image dimensions should not exceed w{max_width} x h{max_height} pixels" +msgstr "" +"Image dimensions should not exceed w{max_width} x h{max_height} pixels!" #: core/validators.py:22 msgid "invalid phone number format" msgstr "Invalid phone number format" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "You can only download the digital asset once" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "favicon not found" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "Geocoding error: {e}" - -#~ msgid "I18N" -#~ msgstr "Internationalization" - -#~ msgid "name" -#~ msgstr "Name" - -#~ msgid "rating" -#~ msgstr "Rating" - -#~ msgid "is business" -#~ msgstr "Is Business" - -#~ msgid "brand slug" -#~ msgstr "Brand's slug" - -#~ msgid "basic info" -#~ msgstr "Basic Info" - -#~ msgid "important dates" -#~ msgstr "Important Dates" - -#~ msgid "eVibes Engine" -#~ msgstr "eVibes Engine" diff --git a/core/locale/en_US/LC_MESSAGES/django.mo b/core/locale/en_US/LC_MESSAGES/django.mo index fb9ef2f3..76bb51d8 100644 Binary files a/core/locale/en_US/LC_MESSAGES/django.mo and b/core/locale/en_US/LC_MESSAGES/django.mo differ diff --git a/core/locale/en_US/LC_MESSAGES/django.po b/core/locale/en_US/LC_MESSAGES/django.po index 640e7f77..9e0a2164 100644 --- a/core/locale/en_US/LC_MESSAGES/django.po +++ b/core/locale/en_US/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,120 +13,116 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "Unique ID" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "Unique ID is used to surely identify any database object" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "Is Active" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" +"if set to false, this object can't be seen by users without needed permission" msgstr "" -"If set to false, this object can't be seen by users without needed " -"permission" +"If set to false, this object can't be seen by users without needed permission" -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "Created" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "When the object first appeared on the database" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "Modified" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "When the object was last edited" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "Translations" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "General" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "Relations" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "Metadata" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "Timestamps" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" msgstr "Activate selected %(verbose_name_plural)s" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)s activated successfully!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "Selected items have been activated!" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" msgstr "Deactivate selected %(verbose_name_plural)s" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "%(verbose_name_plural)s deactivated successfully." +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "Selected items have been deactivated!" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "Attribute Value" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "Attribute Values" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "Image" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "Images" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "Stock" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "Stocks" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "Order Product" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "Order Products" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "Children" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "Config" @@ -178,7 +174,7 @@ msgstr "Momental" msgid "successful" msgstr "Successful" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "Cache I/O" @@ -202,7 +198,7 @@ msgstr "Get application's exposable parameters" msgid "send a message to the support team" msgstr "Send a message to the support team" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "Request a CORSed URL. Only https allowed." @@ -243,8 +239,7 @@ msgid "rewrite an existing attribute group saving non-editables" msgstr "Rewrite an existing attribute group saving non-editables" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" +msgid "rewrite some fields of an existing attribute group saving non-editables" msgstr "" "Rewrite some fields of an existing attribute group saving non-editables" @@ -293,8 +288,7 @@ msgid "rewrite an existing attribute value saving non-editables" msgstr "Rewrite an existing attribute value saving non-editables" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" +msgid "rewrite some fields of an existing attribute value saving non-editables" msgstr "" "Rewrite some fields of an existing attribute value saving non-editables" @@ -332,11 +326,11 @@ msgstr "For non-staff users, only their own orders are returned." #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" #: core/docs/drf/viewsets.py:165 msgid "Filter orders with buy_time >= this ISO 8601 datetime" @@ -368,13 +362,13 @@ msgstr "Filter by order status (case-insensitive substring match)" #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." #: core/docs/drf/viewsets.py:210 msgid "retrieve a single order (detailed view)" @@ -414,7 +408,7 @@ msgstr "" "completed using the user's balance; If `force_payment` is used, a " "transaction is initiated." -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "purchase an order without account creation" @@ -540,17 +534,26 @@ msgstr "" msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…`\n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`\n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`\n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" "`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`,\n" @@ -606,10 +609,12 @@ msgstr "(exact) Digital vs. physical" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" #: core/docs/drf/viewsets.py:441 @@ -732,7 +737,7 @@ msgstr "delete an order–product relation" msgid "add or remove feedback on an order–product relation" msgstr "add or remove feedback on an order–product relation" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "No search term provided." @@ -780,8 +785,8 @@ msgstr "Attributes" msgid "Quantity" msgstr "Quantity" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "Slug" @@ -842,215 +847,238 @@ msgstr "Level" msgid "Product UUID" msgstr "Product UUID" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "Key to look for in or set into the cache" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "Data to store in cache" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "Timeout in seconds to set the data for into the cache" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "Cached data" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "Camelized JSON data from the requested URL" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "Only URLs starting with http(s):// are allowed" -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "Add a product to the order" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "Order {order_uuid} not found" +msgstr "Order {order_uuid} not found!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "Remove a product from the order" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "Remove all products from the order" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "Buy an order" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "Please provide either order_uuid or order_hr_id - mutually exclusive!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "Wrong type came from order.buy() method: {type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "Perform an action on a list of products in the order" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "Remove/Add" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "Action must be either \"add\" or \"remove\"!" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "Perform an action on a list of products in the wishlist" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "Please provide `wishlist_uuid` value." + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "Wishlist {wishlist_uuid} not found!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "Add a product to the order" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "Wishlist {wishlist_uuid} not found" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "Remove a product from the order" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "Remove a product from the order" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "Remove a product from the order" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "Buy an order" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" msgstr "" -"Please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"Please send the attributes as the string formatted like attr1=value1," +"attr2=value2" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "Add or delete a feedback for the orderproduct" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "Action must be either `add` or `remove`!" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "Orderproduct {order_product_uuid} not found!" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "Original address string provided by the user" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} does not exist: {uuid}" +msgstr "{name} does not exist: {uuid}!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "Limit must be between 1 and 10" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - works like a charm" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "Attributes" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "Grouped attributes" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "Groups of attributes" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "Categories" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "Brands" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "Categories" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "Markup Percentage" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "Which attributes and values can be used for filtering this category." -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." +#: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." msgstr "" "Minimum and maximum prices for products in this category, if available." -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "Tags for this category" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "Products in this category" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "Vendors" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "Latitude (Y coordinate)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "Longitude (X coordinate)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "How to" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "Rating value from 1 to 10, inclusive, or 0 if not set." -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "Represents feedback from a user." -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "Notifications" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "Download url for this order product if applicable" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "A list of order products in this order" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "Billing address" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" @@ -1058,729 +1086,726 @@ msgstr "" "Shipping address for this order, leave blank if same as billing address or " "if not applicable" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "Total price of this order" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "Total quantity of products in order" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "Are all of the products in the order digital" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "Transactions for this order" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "Orders" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "Image URL" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "Product's images" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "Category" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "Feedbacks" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "Brand" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "Attribute groups" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "Price" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "Quantity" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "Number of feedbacks" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "Products" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "Promocodes" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "Products on sale" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "Promotions" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "Vendor" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "Product" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "Wishlisted products" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "Wishlists" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "Tagged products" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "Product tags" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "Tagged categories" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "Categories' tags" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "Project name" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "Company Email" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "Company Name" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "Company Address" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "Company Phone Number" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "'email from', sometimes it must be used instead of host user value" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "Email host user" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "Maximum amount for payment" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "Minimum amount for payment" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "Analytics data" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "Advertisement data" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "Configuration" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "Language code" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "Language name" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "Language flag, if exists :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "Get a list of supported languages" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "Products search results" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "Products search results" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "Parent of this group" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "Parent attribute group" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "Attribute group's name" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "Attribute group" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" "Stores credentials and endpoints required for vendor's API communication" -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "Authentication info" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "Define the markup for products retrieved from this vendor" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "Vendor markup percentage" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "Name of this vendor" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "Vendor name" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "Internal tag identifier for the product tag" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "Tag name" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "User-friendly name for the product tag" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "Tag display name" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "Product tag" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "category tag" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "category tags" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "Upload an image representing this category" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "Category image" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "Define a markup percentage for products in this category" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "Parent of this category to form a hierarchical structure" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "Parent category" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "Category name" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "Provide a name for this category" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "Add a detailed description for this category" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "Category description" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "tags that help describe or group this category" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "Priority" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "Name of this brand" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "Brand name" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "Upload a logo representing this brand" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "Brand small image" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "Upload a big logo representing this brand" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "Brand big image" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "Add a detailed description of the brand" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "Brand description" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "Optional categories that this brand is associated with" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "Categories" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "Category this product belongs to" - -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "Optionally associate this product with a brand" - -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "Tags that help describe or group this product" - -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "Indicates whether this product is digitally delivered" - -#: core/models.py:351 -msgid "is product digital" -msgstr "Is product digital" - -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "Provide a clear identifying name for the product" - -#: core/models.py:358 -msgid "product name" -msgstr "Product name" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "Add a detailed description of the product" - -#: core/models.py:364 -msgid "product description" -msgstr "Product description" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "Part number for this product" - -#: core/models.py:372 -msgid "part number" -msgstr "Part number" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "Category of this attribute" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "Group of this attribute" - -#: core/models.py:465 -msgid "string" -msgstr "String" - -#: core/models.py:466 -msgid "integer" -msgstr "Integer" - -#: core/models.py:467 -msgid "float" -msgstr "Float" - -#: core/models.py:468 -msgid "boolean" -msgstr "Boolean" - -#: core/models.py:469 -msgid "array" -msgstr "Array" - -#: core/models.py:470 -msgid "object" -msgstr "Object" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "Type of the attribute's value" - -#: core/models.py:473 -msgid "value type" -msgstr "Value type" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "Name of this attribute" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "Attribute's name" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "Attribute" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "Attribute of this value" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "The specific product associated with this attribute's value" - -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 -msgid "associated product" -msgstr "Associated product" - -#: core/models.py:512 -msgid "the specific value for this attribute" -msgstr "The specific value for this attribute" - -#: core/models.py:528 -msgid "provide alternative text for the image for accessibility" -msgstr "Provide alternative text for the image for accessibility" - -#: core/models.py:529 -msgid "image alt text" -msgstr "Image alt text" - -#: core/models.py:532 -msgid "upload the image file for this product" -msgstr "Upload the image file for this product" - -#: core/models.py:533 core/models.py:558 -msgid "product image" -msgstr "Product image" - -#: core/models.py:539 -msgid "determines the order in which images are displayed" -msgstr "Determines the order in which images are displayed" - -#: core/models.py:540 -msgid "display priority" -msgstr "Display priority" - -#: core/models.py:545 -msgid "the product that this image represents" -msgstr "The product that this image represents" - -#: core/models.py:559 -msgid "product images" -msgstr "Product images" - -#: core/models.py:567 -msgid "percentage discount for the selected products" -msgstr "Percentage discount for the selected products" - -#: core/models.py:568 -msgid "discount percentage" -msgstr "Discount percentage" - -#: core/models.py:573 -msgid "provide a unique name for this promotion" -msgstr "Provide a unique name for this promotion" - -#: core/models.py:574 -msgid "promotion name" -msgstr "Promotion name" - -#: core/models.py:580 -msgid "promotion description" -msgstr "Promotion description" - -#: core/models.py:585 -msgid "select which products are included in this promotion" -msgstr "Select which products are included in this promotion" - -#: core/models.py:586 -msgid "included products" -msgstr "Included products" - -#: core/models.py:590 -msgid "promotion" -msgstr "Promotion" - -#: core/models.py:605 +#: core/models.py:515 msgid "the vendor supplying this product stock" msgstr "The vendor supplying this product stock" -#: core/models.py:606 +#: core/models.py:516 msgid "associated vendor" msgstr "Associated vendor" -#: core/models.py:610 +#: core/models.py:520 msgid "final price to the customer after markups" msgstr "Final price to the customer after markups" -#: core/models.py:611 +#: core/models.py:521 msgid "selling price" msgstr "Selling price" -#: core/models.py:616 +#: core/models.py:526 msgid "the product associated with this stock entry" msgstr "The product associated with this stock entry" -#: core/models.py:624 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "Associated product" + +#: core/models.py:534 msgid "the price paid to the vendor for this product" msgstr "The price paid to the vendor for this product" -#: core/models.py:625 +#: core/models.py:535 msgid "vendor purchase price" msgstr "Vendor purchase price" -#: core/models.py:629 +#: core/models.py:539 msgid "available quantity of the product in stock" msgstr "Available quantity of the product in stock" -#: core/models.py:630 +#: core/models.py:540 msgid "quantity in stock" msgstr "Quantity in stock" -#: core/models.py:634 +#: core/models.py:544 msgid "vendor-assigned SKU for identifying the product" msgstr "Vendor-assigned SKU for identifying the product" -#: core/models.py:635 +#: core/models.py:545 msgid "vendor sku" msgstr "Vendor's SKU" -#: core/models.py:641 +#: core/models.py:551 msgid "digital file associated with this stock if applicable" msgstr "Digital file associated with this stock if applicable" -#: core/models.py:642 +#: core/models.py:552 msgid "digital file" msgstr "Digital file" -#: core/models.py:651 +#: core/models.py:561 msgid "stock entries" msgstr "Stock entries" -#: core/models.py:660 +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "Category this product belongs to" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "Optionally associate this product with a brand" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "Tags that help describe or group this product" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "Indicates whether this product is digitally delivered" + +#: core/models.py:626 +msgid "is product digital" +msgstr "Is product digital" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "Provide a clear identifying name for the product" + +#: core/models.py:633 +msgid "product name" +msgstr "Product name" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "Add a detailed description of the product" + +#: core/models.py:639 +msgid "product description" +msgstr "Product description" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "Part number for this product" + +#: core/models.py:647 +msgid "part number" +msgstr "Part number" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "Category of this attribute" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "Group of this attribute" + +#: core/models.py:767 +msgid "string" +msgstr "String" + +#: core/models.py:768 +msgid "integer" +msgstr "Integer" + +#: core/models.py:769 +msgid "float" +msgstr "Float" + +#: core/models.py:770 +msgid "boolean" +msgstr "Boolean" + +#: core/models.py:771 +msgid "array" +msgstr "Array" + +#: core/models.py:772 +msgid "object" +msgstr "Object" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "Type of the attribute's value" + +#: core/models.py:775 +msgid "value type" +msgstr "Value type" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "Name of this attribute" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "Attribute's name" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "Attribute" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "Attribute of this value" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "The specific product associated with this attribute's value" + +#: core/models.py:837 +msgid "the specific value for this attribute" +msgstr "The specific value for this attribute" + +#: core/models.py:871 +msgid "provide alternative text for the image for accessibility" +msgstr "Provide alternative text for the image for accessibility" + +#: core/models.py:872 +msgid "image alt text" +msgstr "Image alt text" + +#: core/models.py:875 +msgid "upload the image file for this product" +msgstr "Upload the image file for this product" + +#: core/models.py:876 core/models.py:901 +msgid "product image" +msgstr "Product image" + +#: core/models.py:882 +msgid "determines the order in which images are displayed" +msgstr "Determines the order in which images are displayed" + +#: core/models.py:883 +msgid "display priority" +msgstr "Display priority" + +#: core/models.py:888 +msgid "the product that this image represents" +msgstr "The product that this image represents" + +#: core/models.py:902 +msgid "product images" +msgstr "Product images" + +#: core/models.py:943 +msgid "percentage discount for the selected products" +msgstr "Percentage discount for the selected products" + +#: core/models.py:944 +msgid "discount percentage" +msgstr "Discount percentage" + +#: core/models.py:949 +msgid "provide a unique name for this promotion" +msgstr "Provide a unique name for this promotion" + +#: core/models.py:950 +msgid "promotion name" +msgstr "Promotion name" + +#: core/models.py:956 +msgid "promotion description" +msgstr "Promotion description" + +#: core/models.py:961 +msgid "select which products are included in this promotion" +msgstr "Select which products are included in this promotion" + +#: core/models.py:962 +msgid "included products" +msgstr "Included products" + +#: core/models.py:966 +msgid "promotion" +msgstr "Promotion" + +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "Products that the user has marked as wanted" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "User who owns this wishlist" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "Wishlist's Owner" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "Wishlist" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} does not exist: {product_uuid}" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "Documentary" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "Documentaries" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "Unresolved" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "Address line for the customer" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "Address line" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "Street" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "District" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "City" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "Region" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "Postal code" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "Country" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "Geolocation Point(Longitude, Latitude)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "Full JSON response from geocoder for this address" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "Stored JSON response from the geocoding service" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "Address" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "Adresses" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "Unique code used by a user to redeem a discount" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "Promo code identifier" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "Fixed discount amount applied if percent is not used" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "Fixed discount amount" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "Percentage discount applied if fixed amount is not used" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "Percentage discount" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "Timestamp when the promocode expires" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "End validity time" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "Timestamp from which this promocode is valid" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "Start validity time" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "Timestamp when the promocode was used, blank if not used yet" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "Usage timestamp" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "User assigned to this promocode if applicable" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "Assigned user" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "Promo code" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "Promo codes" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." @@ -1788,136 +1813,144 @@ msgstr "" "Only one type of discount should be defined (amount or percent), but not " "both or neither." -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "Promocode has been used already" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "Invalid discount type for promocode {self.uuid}" +msgstr "Invalid discount type for promocode {self.uuid}!" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "The billing address used for this order" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "Optional promo code applied to this order" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "Applied promo code" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "The shipping address used for this order" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "Shipping address" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "Current status of the order in its lifecycle" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "Order status" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" "JSON structure of notifications to display to users, in admin UI the table-" "view is used" -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "JSON representation of order attributes for this order" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "The user who placed the order" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "User" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "The timestamp when the order was finalized" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "Buy time" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "A human-readable identifier for the order" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "human-readable ID" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "Order" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "A user must have only one pending order at a time!" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "You cannot add products to an order that is not a pending one" -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "You cannot add inactive products to order" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "You cannot add more products than available in stock" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "You cannot remove products from an order that is not a pending one" -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "{name} does not exist with query <{query}>" +msgstr "{name} does not exist with query <{query}>!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "Promocode does not exist" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "You can only buy physical products with shipping address specified!" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "Address does not exist" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "" "You can not purchase at this moment, please try again in a few minutes." -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "Invalid force value" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "You cannot purchase an empty order!" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "You cannot buy an order without a user!" + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "A user without a balance cannot buy with balance!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "Insufficient funds to complete the order" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" @@ -1925,117 +1958,120 @@ msgstr "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" msgstr "" "Invalid payment method: {payment_method} from {available_payment_methods}!" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "The price paid by the customer for this product at purchase time" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "Purchase price at order time" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "Internal comments for admins about this ordered product" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "Internal comments" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "User notifications" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "JSON representation of this item's attributes" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "Ordered product attributes" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "Reference to the parent order that contains this product" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "Parent order" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "The specific product associated with this order line" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "Quantity of this specific product in the order" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "Product quantity" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "Current status of this product in the order" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "Product line status" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "Orderproduct must have an associated order!" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "wrong action specified for feedback: {action}" +msgstr "Wrong action specified for feedback: {action}!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "you cannot feedback an order which is not received" -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "Download" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "Downloads" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "You can not download a digital asset for a non-finished order" -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "User-provided comments about their experience with the product" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "Feedback comments" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "" "References the specific product in an order that this feedback is about" -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "Related order product" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "User-assigned rating for the product" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "Product rating" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "Feedback" @@ -2045,13 +2081,13 @@ msgid "" msgstr "" "you must provide a comment, rating, and order product uuid to add feedback." -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "Error during promocode creation: {e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2060,7 +2096,7 @@ msgid "order confirmation" msgstr "Order Confirmation" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2077,21 +2113,22 @@ msgstr "Hello %(order.user.first_name)s," #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" msgstr "" -"Thank you for your order #%(order.pk)s! We are pleased to inform you that we" -" have taken your order into work. Below are the details of your order:" +"Thank you for your order #%(order.pk)s! We are pleased to inform you that we " +"have taken your order into work. Below are the details of your order:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "Total" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2114,20 +2151,20 @@ msgid "best regards,
the %(config.PROJECT_NAME)s team" msgstr "Best regards,
the %(config.PROJECT_NAME)s team" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "All rights reserved" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "Order Delivered" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "Hello %(user_first_name)s," -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" @@ -2136,7 +2173,7 @@ msgstr "" "We have successfully processed your order №%(order_uuid)s! Below are the " "details of your order:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2144,12 +2181,12 @@ msgstr "" "additional\n" " information" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "Value" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -2158,7 +2195,7 @@ msgstr "" "If you have any questions, feel free to contact our support at " "%(contact_email)s." -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Best regards,
the %(project_name)s team" @@ -2170,11 +2207,12 @@ msgstr "Key" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" msgstr "" -"Thank you for your order! We are pleased to confirm your purchase. Below are" -" the details of your order:" +"Thank you for your order! We are pleased to confirm your purchase. Below are " +"the details of your order:" #: core/templates/shipped_order_created_email.html:123 #: core/templates/shipped_order_delivered_email.html:123 @@ -2190,7 +2228,7 @@ msgstr "Your order will be delivered to the following address:" #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "Best regards,
the %(config.PROJECT_NAME)s team" +msgstr "Best regards,
The %(config.PROJECT_NAME)s team" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2209,27 +2247,17 @@ msgstr "Both data and timeout are required" msgid "invalid timeout value, it must be between 0 and 216000 seconds" msgstr "Invalid timeout value, it must be between 0 and 216000 seconds" -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model} must be model" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data} must be list object" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | Contact Us initiated" +msgstr "{config.PROJECT_NAME} | contact us initiated" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" msgstr "{config.PROJECT_NAME} | Order Confirmation" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" msgstr "{config.PROJECT_NAME} | Order Delivered" @@ -2246,21 +2274,21 @@ msgstr "NOMINATIM_URL parameter must be configured!" #, python-brace-format msgid "image dimensions should not exceed w{max_width} x h{max_height} pixels" msgstr "" -"Image dimensions should not exceed w{max_width} x h{max_height} pixels" +"Image dimensions should not exceed w{max_width} x h{max_height} pixels!" #: core/validators.py:22 msgid "invalid phone number format" msgstr "Invalid phone number format" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "You can only download the digital asset once" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "favicon not found" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "Geocoding error: {e}" diff --git a/core/locale/es_ES/LC_MESSAGES/django.mo b/core/locale/es_ES/LC_MESSAGES/django.mo index 85c222c7..6347fe2c 100644 Binary files a/core/locale/es_ES/LC_MESSAGES/django.mo and b/core/locale/es_ES/LC_MESSAGES/django.mo differ diff --git a/core/locale/es_ES/LC_MESSAGES/django.po b/core/locale/es_ES/LC_MESSAGES/django.po index 4bd2f4e6..ea18d7c6 100644 --- a/core/locale/es_ES/LC_MESSAGES/django.po +++ b/core/locale/es_ES/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,122 +13,119 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "Identificación única" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "" "El identificador único se utiliza para identificar con seguridad cualquier " "objeto de la base de datos" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "Está activo" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" +"if set to false, this object can't be seen by users without needed permission" msgstr "" "Si se establece en false, este objeto no puede ser visto por los usuarios " "sin el permiso necesario" -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "Creado" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "Cuando el objeto apareció por primera vez en la base de datos" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "Modificado" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "Cuándo se editó el objeto por última vez" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "Traducciones" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "General" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "Relaciones" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "Metadatos" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "Marcas de tiempo" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" -msgstr "Activar %(verbose_name_plural)s seleccionados" +msgstr "Activar %(verbose_name_plural)s seleccionado" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "¡%(verbose_name_plural)s activado con éxito!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "Los artículos seleccionados se han activado." -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" -msgstr "Desactivar %(verbose_name_plural)s seleccionados" +msgstr "Desactivar %(verbose_name_plural)s seleccionado" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "%(verbose_name_plural)s desactivado con éxito." +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "Los artículos seleccionados se han desactivado." -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "Atributo Valor" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "Valores de los atributos" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "Imagen" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "Imágenes" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "Stock" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "Acciones" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "Pedir un producto" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "Pedir productos" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "Niños" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "Configurar" @@ -180,7 +177,7 @@ msgstr "Momento" msgid "successful" msgstr "Éxito" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "E/S de caché" @@ -190,7 +187,8 @@ msgid "" "apply key, data and timeout with authentication to write data to cache." msgstr "" "Aplicar sólo una clave para leer datos permitidos de la caché.\n" -"Aplicar clave, datos y tiempo de espera con autenticación para escribir datos en la caché." +"Aplicar clave, datos y tiempo de espera con autenticación para escribir " +"datos en la caché." #: core/docs/drf/views.py:32 msgid "get a list of supported languages" @@ -204,7 +202,7 @@ msgstr "Obtener los parámetros exponibles de la aplicación" msgid "send a message to the support team" msgstr "Enviar un mensaje al equipo de asistencia" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "Solicitar una URL CORSed. Solo se permite https." @@ -222,8 +220,8 @@ msgid "" "purchase an order as a business, using the provided `products` with " "`product_uuid` and `attributes`." msgstr "" -"Compra un pedido como empresa, utilizando los `productos` proporcionados con" -" `product_uuid` y `attributes`." +"Compra un pedido como empresa, utilizando los `productos` proporcionados con " +"`product_uuid` y `attributes`." #: core/docs/drf/viewsets.py:43 msgid "list all attribute groups (simple view)" @@ -246,8 +244,7 @@ msgid "rewrite an existing attribute group saving non-editables" msgstr "Reescribir un grupo de atributos existente guardando los no editables" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" +msgid "rewrite some fields of an existing attribute group saving non-editables" msgstr "" "Reescribir algunos campos de un grupo de atributos existente guardando los " "no editables" @@ -275,8 +272,7 @@ msgstr "Reescribir un atributo existente guardando los no editables" #: core/docs/drf/viewsets.py:90 msgid "rewrite some fields of an existing attribute saving non-editables" msgstr "" -"Reescribir algunos campos de un atributo existente guardando los no " -"editables" +"Reescribir algunos campos de un atributo existente guardando los no editables" #: core/docs/drf/viewsets.py:97 msgid "list all attribute values (simple view)" @@ -299,11 +295,10 @@ msgid "rewrite an existing attribute value saving non-editables" msgstr "Reescribir un valor de atributo existente guardando los no editables" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" +msgid "rewrite some fields of an existing attribute value saving non-editables" msgstr "" -"Reescribir algunos campos de un valor de atributo existente guardando los no" -" editables" +"Reescribir algunos campos de un valor de atributo existente guardando los no " +"editables" #: core/docs/drf/viewsets.py:124 msgid "list all categories (simple view)" @@ -343,12 +338,12 @@ msgstr "" #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" "Búsqueda de subcadenas sin distinción entre mayúsculas y minúsculas en " -"human_readable_id, order_products.product.name y " -"order_products.product.partnumber" +"human_readable_id, order_products.product.name y order_products.product." +"partnumber" #: core/docs/drf/viewsets.py:165 msgid "Filter orders with buy_time >= this ISO 8601 datetime" @@ -369,8 +364,8 @@ msgstr "Filtrar por ID de pedido exacto legible por el ser humano" #: core/docs/drf/viewsets.py:185 msgid "Filter by user's email (case-insensitive exact match)" msgstr "" -"Filtrar por correo electrónico del usuario (coincidencia exacta insensible a" -" mayúsculas y minúsculas)" +"Filtrar por correo electrónico del usuario (coincidencia exacta insensible a " +"mayúsculas y minúsculas)" #: core/docs/drf/viewsets.py:190 msgid "Filter by user's UUID" @@ -384,9 +379,9 @@ msgstr "" #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" "Ordenar por: uuid, human_readable_id, user_email, user, status, created, " "modified, buy_time, random. Utilice el prefijo '-' para orden descendente " @@ -432,7 +427,7 @@ msgstr "" "finaliza utilizando el saldo del usuario; Si se utiliza `force_payment`, se " "inicia una transacción." -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "comprar un pedido sin crear una cuenta" @@ -521,8 +516,7 @@ msgstr "Reescribir un atributo existente guardando los no editables" #: core/docs/drf/viewsets.py:303 msgid "rewrite some fields of an existing wishlist saving non-editables" msgstr "" -"Reescribir algunos campos de un atributo existente guardando los no " -"editables" +"Reescribir algunos campos de un atributo existente guardando los no editables" #: core/docs/drf/viewsets.py:307 msgid "add product to wishlist" @@ -569,20 +563,31 @@ msgstr "" msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "Filtrar por uno o varios pares nombre/valor de atributo. \n" "- Sintaxis**: `nombre_attr=método-valor[;attr2=método2-valor2]...`.\n" -"- Métodos** (por defecto `icontiene` si se omite): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`.\n" -"- Tipificación de valores**: Se intenta primero JSON (para poder pasar listas/dictos), `true`/`false` para booleanos, enteros, flotantes; en caso contrario se trata como cadena. \n" -"- Base64**: prefiérelo con `b64-` para codificar en base64 el valor sin procesar. \n" +"- Métodos** (por defecto `icontiene` si se omite): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`.\n" +"- Tipificación de valores**: Se intenta primero JSON (para poder pasar " +"listas/dictos), `true`/`false` para booleanos, enteros, flotantes; en caso " +"contrario se trata como cadena. \n" +"- Base64**: prefiérelo con `b64-` para codificar en base64 el valor sin " +"procesar. \n" "Ejemplos: \n" -"`color=rojo exacto`, `tamaño=gt-10`, `características=en-[\"wifi\", \"bluetooth\"]`,\n" +"`color=rojo exacto`, `tamaño=gt-10`, `características=en-[\"wifi\", " +"\"bluetooth\"]`,\n" "`b64-description=icontains-aGVhdC1jb2xk`." #: core/docs/drf/viewsets.py:349 @@ -637,10 +642,12 @@ msgstr "(exacto) Digital frente a físico" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" -"Lista separada por comas de campos por los que ordenar. Prefiérela con `-` para que sea descendente. \n" +"Lista separada por comas de campos por los que ordenar. Prefiérela con `-` " +"para que sea descendente. \n" "**Permitido:** uuid, rating, name, slug, created, modified, price, random" #: core/docs/drf/viewsets.py:441 @@ -768,7 +775,7 @@ msgstr "suprimir una relación pedido-producto" msgid "add or remove feedback on an order–product relation" msgstr "añadir o eliminar comentarios en una relación pedido-producto" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "No se proporciona ningún término de búsqueda." @@ -816,8 +823,8 @@ msgstr "Atributos" msgid "Quantity" msgstr "Cantidad" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "Babosa" @@ -831,8 +838,7 @@ msgstr "Incluir subcategorías" #: core/filters.py:147 msgid "there must be a category_uuid to use include_subcategories flag" -msgstr "" -"Debe haber un category_uuid para usar la bandera include_subcategories" +msgstr "Debe haber un category_uuid para usar la bandera include_subcategories" #: core/filters.py:280 msgid "Search (ID, product name or part number)" @@ -879,220 +885,241 @@ msgstr "Nivel" msgid "Product UUID" msgstr "UUID del producto" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "Clave que hay que buscar o introducir en la caché" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "Datos a almacenar en caché" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "Tiempo de espera en segundos para poner los datos en la caché" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "Datos en caché" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "Datos JSON camelizados de la URL solicitada" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "Sólo se permiten URL que empiecen por http(s)://." -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "Añadir un producto al pedido" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "Pedido {order_uuid} no encontrado" +msgstr "Pedido {order_uuid} ¡no encontrado!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "Eliminar un producto del pedido" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "Eliminar todos los productos del pedido" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "Comprar un pedido" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "Indique order_uuid o order_hr_id, ¡se excluyen mutuamente!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" -msgstr "" -"Tipo incorrecto proveniente del método order.buy(): {type(instance)!s}" +msgstr "Tipo incorrecto proveniente del método order.buy(): {type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "Realizar una acción en una lista de productos del pedido" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "Quitar/Agregar" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "La acción debe ser \"añadir\" o \"eliminar\"." -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "Realizar una acción en una lista de productos de la lista de deseos" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "Por favor, proporcione el valor `wishlist_uuid`." + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "Lista de deseos {wishlist_uuid} ¡no encontrada!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "Añadir un producto al pedido" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "Lista de deseos {wishlist_uuid} no encontrada" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "Eliminar un producto del pedido" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "Eliminar un producto del pedido" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "Eliminar un producto del pedido" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "Comprar un pedido" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" msgstr "" -"Por favor, envíe los atributos como una cadena formateada como " -"attr1=valor1,attr2=valor2" +"Por favor, envíe los atributos como una cadena formateada como attr1=valor1," +"attr2=valor2" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "Añadir o eliminar un comentario para el pedido-producto" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "La acción debe ser \"añadir\" o \"eliminar\"." + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "No se ha encontrado el producto {order_product_uuid}." + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "Cadena de dirección original proporcionada por el usuario" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} no existe: {uuid}" +msgstr "{name} no existe: ¡{uuid}!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "El límite debe estar entre 1 y 10" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - funciona a las mil maravillas" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "Atributos" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "Atributos agrupados" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "Grupos de atributos" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "Categorías" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "Marcas" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "Categorías" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "Porcentaje de recargo" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "" "Qué atributos y valores se pueden utilizar para filtrar esta categoría." -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." +#: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." msgstr "" "Precios mínimo y máximo de los productos de esta categoría, si están " "disponibles." -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "Etiquetas para esta categoría" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "Productos de esta categoría" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "Vendedores" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "Latitud (coordenada Y)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "Longitud (coordenada X)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "Cómo" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "" -"Valor de calificación de 1 a 10, ambos inclusive, o 0 si no está " -"configurado." +"Valor de calificación de 1 a 10, ambos inclusive, o 0 si no está configurado." -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "Representa la opinión de un usuario." -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "Notificaciones" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "Descargar url para este producto de pedido si procede" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "Una lista de los productos del pedido" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "Dirección de facturación" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" @@ -1100,735 +1127,732 @@ msgstr "" "Dirección de envío para este pedido, dejar en blanco si es la misma que la " "de facturación o si no procede" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "Precio total de este pedido" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "Cantidad total de productos del pedido" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "¿Están todos los productos en el pedido digital" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "Transacciones para este pedido" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "Pedidos" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "URL de la imagen" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "Imágenes del producto" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "Categoría" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "Comentarios" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "Marca" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "Grupos de atributos" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "Precio" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "Cantidad" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "Número de reacciones" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "Productos" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "Códigos promocionales" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "Productos a la venta" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "Promociones" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "Vendedor" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "Producto" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "Productos deseados" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "Listas de deseos" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "Productos con etiqueta" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "Etiquetas del producto" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "Categorías" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "Etiquetas de las categorías" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "Nombre del proyecto" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "Correo electrónico de la empresa" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "Nombre de la empresa" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "Dirección de la empresa" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "Teléfono de la empresa" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "" "'email from', a veces debe utilizarse en lugar del valor del usuario host" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "Correo electrónico del usuario anfitrión" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "Importe máximo de pago" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "Importe mínimo de pago" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "Datos analíticos" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "Datos publicitarios" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "Configuración" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "Código de idioma" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "Nombre de la lengua" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "Bandera de idioma, si existe :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "Obtener una lista de los idiomas admitidos" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "Resultados de la búsqueda de productos" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "Resultados de la búsqueda de productos" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "Padre de este grupo" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "Grupo de atributos padre" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "Nombre del grupo de atributos" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "Grupo de atributos" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" "Almacena las credenciales y los puntos finales necesarios para la " "comunicación API del proveedor" -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "Información de autenticación" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "" "Definir el margen de beneficio para los productos recuperados de este " "proveedor" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "Porcentaje de margen del vendedor" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "Nombre de este vendedor" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "Nombre del vendedor" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "Identificador interno de la etiqueta del producto" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "Nombre de la etiqueta" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "Nombre fácil de usar para la etiqueta del producto" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "Nombre de la etiqueta" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "Etiqueta del producto" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "etiqueta de categoría" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "etiquetas de categoría" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "Cargar una imagen que represente esta categoría" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "Categoría imagen" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "Definir un porcentaje de recargo para los productos de esta categoría" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "Padre de esta categoría para formar una estructura jerárquica" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "Categoría de padres" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "Nombre de la categoría" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "Indique un nombre para esta categoría" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "Añadir una descripción detallada para esta categoría" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "Descripción de la categoría" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "etiquetas que ayudan a describir o agrupar esta categoría" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "Prioridad" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "Nombre de esta marca" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "Marca" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "Cargar un logotipo que represente a esta marca" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "Marca pequeña imagen" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "Sube un logotipo grande que represente a esta marca" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "Gran imagen de marca" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "Añadir una descripción detallada de la marca" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "Descripción de la marca" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "Categorías opcionales a las que se asocia esta marca" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "Categorías" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "Categoría a la que pertenece este producto" +#: core/models.py:515 +msgid "the vendor supplying this product stock" +msgstr "El vendedor que suministra este producto dispone de" -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "Si lo desea, puede asociar este producto a una marca" +#: core/models.py:516 +msgid "associated vendor" +msgstr "Proveedor asociado" -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "Etiquetas que ayudan a describir o agrupar este producto" +#: core/models.py:520 +msgid "final price to the customer after markups" +msgstr "Precio final al cliente después de márgenes" -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "Indica si este producto se entrega digitalmente" +#: core/models.py:521 +msgid "selling price" +msgstr "Precio de venta" -#: core/models.py:351 -msgid "is product digital" -msgstr "¿Es digital el producto?" +#: core/models.py:526 +msgid "the product associated with this stock entry" +msgstr "El producto asociado a esta entrada en stock" -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "Proporcionar un nombre que identifique claramente el producto" - -#: core/models.py:358 -msgid "product name" -msgstr "Nombre del producto" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "Añada una descripción detallada del producto" - -#: core/models.py:364 -msgid "product description" -msgstr "Descripción del producto" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "Número de pieza de este producto" - -#: core/models.py:372 -msgid "part number" -msgstr "Número de pieza" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "Categoría de este atributo" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "Grupo de este atributo" - -#: core/models.py:465 -msgid "string" -msgstr "Cadena" - -#: core/models.py:466 -msgid "integer" -msgstr "Entero" - -#: core/models.py:467 -msgid "float" -msgstr "Flotador" - -#: core/models.py:468 -msgid "boolean" -msgstr "Booleano" - -#: core/models.py:469 -msgid "array" -msgstr "Matriz" - -#: core/models.py:470 -msgid "object" -msgstr "Objeto" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "Tipo del valor del atributo" - -#: core/models.py:473 -msgid "value type" -msgstr "Tipo de valor" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "Nombre de este atributo" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "Nombre del atributo" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "Atributo" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "Atributo de este valor" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "El producto específico asociado al valor de este atributo" - -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 msgid "associated product" msgstr "Producto asociado" -#: core/models.py:512 +#: core/models.py:534 +msgid "the price paid to the vendor for this product" +msgstr "El precio pagado al vendedor por este producto" + +#: core/models.py:535 +msgid "vendor purchase price" +msgstr "Precio de compra al vendedor" + +#: core/models.py:539 +msgid "available quantity of the product in stock" +msgstr "Cantidad disponible del producto en stock" + +#: core/models.py:540 +msgid "quantity in stock" +msgstr "Cantidad en stock" + +#: core/models.py:544 +msgid "vendor-assigned SKU for identifying the product" +msgstr "SKU asignada por el proveedor para identificar el producto" + +#: core/models.py:545 +msgid "vendor sku" +msgstr "SKU del vendedor" + +#: core/models.py:551 +msgid "digital file associated with this stock if applicable" +msgstr "Archivo digital asociado a esta acción, si procede" + +#: core/models.py:552 +msgid "digital file" +msgstr "Archivo digital" + +#: core/models.py:561 +msgid "stock entries" +msgstr "Entradas en existencias" + +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "Categoría a la que pertenece este producto" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "Si lo desea, puede asociar este producto a una marca" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "Etiquetas que ayudan a describir o agrupar este producto" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "Indica si este producto se entrega digitalmente" + +#: core/models.py:626 +msgid "is product digital" +msgstr "¿Es digital el producto?" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "Proporcionar un nombre que identifique claramente el producto" + +#: core/models.py:633 +msgid "product name" +msgstr "Nombre del producto" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "Añada una descripción detallada del producto" + +#: core/models.py:639 +msgid "product description" +msgstr "Descripción del producto" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "Número de pieza de este producto" + +#: core/models.py:647 +msgid "part number" +msgstr "Número de pieza" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "Categoría de este atributo" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "Grupo de este atributo" + +#: core/models.py:767 +msgid "string" +msgstr "Cadena" + +#: core/models.py:768 +msgid "integer" +msgstr "Entero" + +#: core/models.py:769 +msgid "float" +msgstr "Flotador" + +#: core/models.py:770 +msgid "boolean" +msgstr "Booleano" + +#: core/models.py:771 +msgid "array" +msgstr "Matriz" + +#: core/models.py:772 +msgid "object" +msgstr "Objeto" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "Tipo del valor del atributo" + +#: core/models.py:775 +msgid "value type" +msgstr "Tipo de valor" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "Nombre de este atributo" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "Nombre del atributo" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "Atributo" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "Atributo de este valor" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "El producto específico asociado al valor de este atributo" + +#: core/models.py:837 msgid "the specific value for this attribute" msgstr "El valor específico de este atributo" -#: core/models.py:528 +#: core/models.py:871 msgid "provide alternative text for the image for accessibility" msgstr "" "Proporcione un texto alternativo para la imagen en aras de la accesibilidad" -#: core/models.py:529 +#: core/models.py:872 msgid "image alt text" msgstr "Texto alternativo de la imagen" -#: core/models.py:532 +#: core/models.py:875 msgid "upload the image file for this product" msgstr "Cargar el archivo de imagen para este producto" -#: core/models.py:533 core/models.py:558 +#: core/models.py:876 core/models.py:901 msgid "product image" msgstr "Imagen del producto" -#: core/models.py:539 +#: core/models.py:882 msgid "determines the order in which images are displayed" msgstr "Determina el orden de visualización de las imágenes" -#: core/models.py:540 +#: core/models.py:883 msgid "display priority" msgstr "Prioridad de visualización" -#: core/models.py:545 +#: core/models.py:888 msgid "the product that this image represents" msgstr "El producto que representa esta imagen" -#: core/models.py:559 +#: core/models.py:902 msgid "product images" msgstr "Imágenes de productos" -#: core/models.py:567 +#: core/models.py:943 msgid "percentage discount for the selected products" msgstr "Porcentaje de descuento para los productos seleccionados" -#: core/models.py:568 +#: core/models.py:944 msgid "discount percentage" msgstr "Porcentaje de descuento" -#: core/models.py:573 +#: core/models.py:949 msgid "provide a unique name for this promotion" msgstr "Proporcione un nombre único para esta promoción" -#: core/models.py:574 +#: core/models.py:950 msgid "promotion name" msgstr "Nombre de la promoción" -#: core/models.py:580 +#: core/models.py:956 msgid "promotion description" msgstr "Descripción de la promoción" -#: core/models.py:585 +#: core/models.py:961 msgid "select which products are included in this promotion" msgstr "Seleccione los productos incluidos en esta promoción" -#: core/models.py:586 +#: core/models.py:962 msgid "included products" msgstr "Productos incluidos" -#: core/models.py:590 +#: core/models.py:966 msgid "promotion" msgstr "Promoción" -#: core/models.py:605 -msgid "the vendor supplying this product stock" -msgstr "El vendedor que suministra este producto dispone de" - -#: core/models.py:606 -msgid "associated vendor" -msgstr "Proveedor asociado" - -#: core/models.py:610 -msgid "final price to the customer after markups" -msgstr "Precio final al cliente después de márgenes" - -#: core/models.py:611 -msgid "selling price" -msgstr "Precio de venta" - -#: core/models.py:616 -msgid "the product associated with this stock entry" -msgstr "El producto asociado a esta entrada en stock" - -#: core/models.py:624 -msgid "the price paid to the vendor for this product" -msgstr "El precio pagado al vendedor por este producto" - -#: core/models.py:625 -msgid "vendor purchase price" -msgstr "Precio de compra al vendedor" - -#: core/models.py:629 -msgid "available quantity of the product in stock" -msgstr "Cantidad disponible del producto en stock" - -#: core/models.py:630 -msgid "quantity in stock" -msgstr "Cantidad en stock" - -#: core/models.py:634 -msgid "vendor-assigned SKU for identifying the product" -msgstr "SKU asignada por el proveedor para identificar el producto" - -#: core/models.py:635 -msgid "vendor sku" -msgstr "SKU del vendedor" - -#: core/models.py:641 -msgid "digital file associated with this stock if applicable" -msgstr "Archivo digital asociado a esta acción, si procede" - -#: core/models.py:642 -msgid "digital file" -msgstr "Archivo digital" - -#: core/models.py:651 -msgid "stock entries" -msgstr "Entradas en existencias" - -#: core/models.py:660 +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "Productos que el usuario ha marcado como deseados" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "Usuario propietario de esta lista de deseos" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "Propietario de Wishlist" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "Lista de deseos" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} no existe: {product_uuid}" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "Documental" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "Documentaries" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "Sin resolver" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "Dirección del cliente" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "Dirección" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "Calle" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "Distrito" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "Ciudad" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "Región" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "Promo code" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "País" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "Geolocalización Punto(Longitud, Latitud)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "Respuesta JSON completa del geocodificador para esta dirección" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "Respuesta JSON almacenada del servicio de geocodificación" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "Dirección" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "Direcciones" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "Código único utilizado por un usuario para canjear un descuento" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "Promo code identifier" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "Se aplica un descuento fijo si no se utiliza el porcentaje" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "Importe fijo del descuento" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "Porcentaje de descuento aplicado si no se utiliza el importe fijo" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "Porcentaje de descuento" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "Fecha de caducidad del promocode" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "Hora de fin de validez" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "Fecha a partir de la cual es válido este promocode" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "Hora de inicio de validez" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "" "Fecha en la que se utilizó el promocode, en blanco si aún no se ha utilizado" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "Marca de tiempo de uso" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "Usuario asignado a este promocode si procede" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "Usuario asignado" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "Promo code" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "Promo codes" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." @@ -1836,138 +1860,146 @@ msgstr "" "Sólo debe definirse un tipo de descuento (importe o porcentaje), pero no " "ambos ni ninguno." -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "El código promocional ya ha sido utilizado" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "Tipo de descuento no válido para promocode {self.uuid}" +msgstr "¡Tipo de descuento no válido para el código promocional {self.uuid}!" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "La dirección de facturación utilizada para este pedido" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "Código promocional opcional aplicado a este pedido" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "Código promocional aplicado" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "La dirección de envío utilizada para este pedido" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "Dirección de envío" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "Estado actual del pedido en su ciclo de vida" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "Estado del pedido" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" "Estructura JSON de las notificaciones para mostrar a los usuarios, en la " "interfaz de administración se utiliza la vista de tabla." -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "Representación JSON de los atributos de la orden para esta orden" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "El usuario que realizó el pedido" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "Usuario" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "Fecha de finalización de la orden" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "Comprar tiempo" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "Un identificador legible por el ser humano para la orden" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "ID legible por humanos" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "Pida" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "Un usuario sólo puede tener una orden pendiente a la vez." -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "No puede añadir productos a un pedido que no esté pendiente" -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "No se pueden añadir productos inactivos al pedido" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "No puede añadir más productos de los disponibles en stock" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "No puede eliminar productos de un pedido que no esté pendiente" -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "{name} no existe con la consulta <{query}>" +msgstr "{name} ¡no existe con la consulta <{query}>!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "Promocode no existe" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "" "Sólo puede comprar productos físicos con la dirección de envío especificada." -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "La dirección no existe" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "" "No puede comprar en este momento, por favor inténtelo de nuevo en unos " "minutos." -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "Valor de fuerza no válido" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "No se puede comprar un pedido vacío." -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "No se puede comprar un pedido sin un usuario." + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "¡Un usuario sin saldo no puede comprar con saldo!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "Fondos insuficientes para completar el pedido" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" @@ -1975,120 +2007,123 @@ msgstr "" "no puede comprar sin registrarse, facilite la siguiente información: nombre " "del cliente, correo electrónico del cliente, número de teléfono del cliente" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" msgstr "" "Forma de pago no válida: ¡{payment_method} de {available_payment_methods}!" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "" "El precio pagado por el cliente por este producto en el momento de la compra" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "Precio de compra en el momento del pedido" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "" "Comentarios internos para los administradores sobre este producto solicitado" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "Comentarios internos" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "Notificaciones a los usuarios" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "Representación JSON de los atributos de este elemento" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "Atributos ordenados del producto" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "Referencia al pedido principal que contiene este producto" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "Orden de los padres" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "El producto específico asociado a esta línea de pedido" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "Cantidad de este producto específico en el pedido" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "Cantidad de productos" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "Estado actual de este producto en el pedido" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "Estado de la línea de productos" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "El pedido-producto debe tener un pedido asociado." + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "acción incorrecta especificada para la retroalimentación: {action}" +msgstr "Acción incorrecta especificada para la retroalimentación: ¡{action}!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "no se puede comentar un pedido no recibido" -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "Descargar" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "Descargas" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "No puede descargar un activo digital para un pedido no finalizado" -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "Comentarios de los usuarios sobre su experiencia con el producto" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "Comentarios" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "" "Hace referencia al producto específico de un pedido sobre el que trata esta " "opinión" -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "Producto relacionado con el pedido" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "Valoración del producto asignada por el usuario" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "Valoración del producto" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "Comentarios" @@ -2099,13 +2134,13 @@ msgstr "" "debe proporcionar un comentario, una valoración y el uuid del producto " "solicitado para añadir comentarios." -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "Error durante la creación del promocode: {e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2114,7 +2149,7 @@ msgid "order confirmation" msgstr "Confirmación de pedido" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2131,21 +2166,22 @@ msgstr "Hola %(order.user.first_name)s," #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" msgstr "" "¡Gracias por su pedido #%(order.pk)s! Nos complace informarle de que hemos " "recibido su pedido. A continuación encontrará los detalles de su pedido:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "Total" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2165,23 +2201,23 @@ msgstr "" #: core/templates/digital_order_created_email.html:133 #, python-format msgid "best regards,
the %(config.PROJECT_NAME)s team" -msgstr "Saludos cordiales,
el equipo de %(config.PROJECT_NAME)s" +msgstr "Saludos cordiales,
el equipo %(config.PROJECT_NAME)s" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "Todos los derechos reservados" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "Pedido entregado" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "Hola %(user_first_name)s," -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" @@ -2190,7 +2226,7 @@ msgstr "" "¡Hemos procesado correctamente su pedido №%(order_uuid)s! A continuación " "encontrará los detalles de su pedido:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2198,12 +2234,12 @@ msgstr "" "información adicional\n" " información adicional" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "Valor" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -2212,10 +2248,10 @@ msgstr "" "Si tiene alguna pregunta, no dude en ponerse en contacto con nuestro " "servicio de asistencia en %(contact_email)s." -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Saludos cordiales,
el equipo de %(project_name)s" +msgstr "Saludos cordiales,
el equipo %(project_name)s" #: core/templates/json_table_widget.html:5 msgid "key" @@ -2224,7 +2260,8 @@ msgstr "Clave" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" msgstr "" "Gracias por su pedido. Nos complace confirmarle su compra. A continuación " @@ -2244,7 +2281,7 @@ msgstr "Su pedido se entregará en la siguiente dirección:" #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "Saludos cordiales,
el equipo de %(config.PROJECT_NAME)s" +msgstr "Saludos cordiales,
El equipo %(config.PROJECT_NAME)s" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2264,27 +2301,17 @@ msgid "invalid timeout value, it must be between 0 and 216000 seconds" msgstr "" "Valor de tiempo de espera no válido, debe estar entre 0 y 216000 segundos." -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model} debe ser modelo" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data} debe ser un objeto de lista" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | Contacto iniciado" +msgstr "{config.PROJECT_NAME} | contacto iniciado" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" msgstr "{config.PROJECT_NAME} | Confirmación de pedido" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" msgstr "{config.PROJECT_NAME} | Pedido entregado" @@ -2308,15 +2335,15 @@ msgstr "" msgid "invalid phone number format" msgstr "Formato de número de teléfono no válido" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "Sólo puede descargar el activo digital una vez" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "favicon no encontrado" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "Error de geocodificación: {e}" diff --git a/core/locale/fr_FR/LC_MESSAGES/django.mo b/core/locale/fr_FR/LC_MESSAGES/django.mo index 7efaee64..bc856c1c 100644 Binary files a/core/locale/fr_FR/LC_MESSAGES/django.mo and b/core/locale/fr_FR/LC_MESSAGES/django.mo differ diff --git a/core/locale/fr_FR/LC_MESSAGES/django.po b/core/locale/fr_FR/LC_MESSAGES/django.po index 20b653a6..1ca76be8 100644 --- a/core/locale/fr_FR/LC_MESSAGES/django.po +++ b/core/locale/fr_FR/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,122 +13,119 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "Unique ID" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "" "L'identifiant unique est utilisé pour identifier de manière sûre tout objet " "de la base de données." -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "Est actif" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" +"if set to false, this object can't be seen by users without needed permission" msgstr "" "Si la valeur est fixée à false, cet objet ne peut pas être vu par les " "utilisateurs qui n'ont pas l'autorisation nécessaire." -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "Créée" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "Date de la première apparition de l'objet dans la base de données" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "Modifié" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "Date de la dernière modification de l'objet" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "Traductions" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "Général" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "Relations" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "Métadonnées" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "Horodatage" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" -msgstr "Activer les %(verbose_name_plural)s sélectionnés" +msgstr "Activer la %(verbose_name_plural)s sélectionnée" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)s activé avec succès !" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "Les articles sélectionnés ont été activés !" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" -msgstr "Désactiver les %(verbose_name_plural)s sélectionnés" +msgstr "Désactiver la %(verbose_name_plural)s sélectionnée" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "Désactivation réussie de %(verbose_name_plural)s." +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "Les articles sélectionnés ont été désactivés !" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "Valeur de l'attribut" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "Valeurs des attributs" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "Image" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "Images" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "Stock" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "Stocks" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "Commander un produit" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "Commander des produits" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "Les enfants" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "Config" @@ -180,7 +177,7 @@ msgstr "Momental" msgid "successful" msgstr "Réussite" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "Cache I/O" @@ -189,8 +186,10 @@ msgid "" "apply only a key to read permitted data from cache.\n" "apply key, data and timeout with authentication to write data to cache." msgstr "" -"Appliquer uniquement une clé pour lire les données autorisées dans la mémoire cache.\n" -"Appliquer une clé, des données et un délai d'attente avec authentification pour écrire des données dans la mémoire cache." +"Appliquer uniquement une clé pour lire les données autorisées dans la " +"mémoire cache.\n" +"Appliquer une clé, des données et un délai d'attente avec authentification " +"pour écrire des données dans la mémoire cache." #: core/docs/drf/views.py:32 msgid "get a list of supported languages" @@ -204,7 +203,7 @@ msgstr "Obtenir les paramètres exposables de l'application" msgid "send a message to the support team" msgstr "Envoyer un message à l'équipe d'assistance" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "Demander une URL CORSée. Seul https est autorisé." @@ -248,8 +247,7 @@ msgstr "" "modifiables" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" +msgid "rewrite some fields of an existing attribute group saving non-editables" msgstr "" "Réécrire certains champs d'un groupe d'attributs existant en sauvegardant " "les non-éditables" @@ -278,8 +276,8 @@ msgstr "" #: core/docs/drf/viewsets.py:90 msgid "rewrite some fields of an existing attribute saving non-editables" msgstr "" -"Réécrire certains champs d'un attribut existant en sauvegardant les éléments" -" non modifiables" +"Réécrire certains champs d'un attribut existant en sauvegardant les éléments " +"non modifiables" #: core/docs/drf/viewsets.py:97 msgid "list all attribute values (simple view)" @@ -304,8 +302,7 @@ msgstr "" "modifiables" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" +msgid "rewrite some fields of an existing attribute value saving non-editables" msgstr "" "Réécrire certains champs d'une valeur d'attribut existante en sauvegardant " "les éléments non modifiables" @@ -348,11 +345,11 @@ msgstr "" #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" -"Recherche insensible à la casse dans human_readable_id, " -"order_products.product.name, et order_products.product.partnumber" +"Recherche insensible à la casse dans human_readable_id, order_products." +"product.name, et order_products.product.partnumber" #: core/docs/drf/viewsets.py:165 msgid "Filter orders with buy_time >= this ISO 8601 datetime" @@ -388,13 +385,13 @@ msgstr "" #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" "Ordonner par l'un des éléments suivants : uuid, human_readable_id, " -"user_email, user, status, created, modified, buy_time, random. Préfixer avec" -" '-' pour l'ordre décroissant (par exemple '-buy_time')." +"user_email, user, status, created, modified, buy_time, random. Préfixer avec " +"'-' pour l'ordre décroissant (par exemple '-buy_time')." #: core/docs/drf/viewsets.py:210 msgid "retrieve a single order (detailed view)" @@ -432,11 +429,11 @@ msgid "" "completed using the user's balance; if `force_payment` is used, a " "transaction is initiated." msgstr "" -"Finalise l'achat de la commande. Si `force_balance` est utilisé, l'achat est" -" complété en utilisant le solde de l'utilisateur ; Si `force_payment` est " +"Finalise l'achat de la commande. Si `force_balance` est utilisé, l'achat est " +"complété en utilisant le solde de l'utilisateur ; Si `force_payment` est " "utilisé, une transaction est initiée." -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "acheter une commande sans créer de compte" @@ -493,8 +490,8 @@ msgid "" "removes a list of products from an order using the provided `product_uuid` " "and `attributes`" msgstr "" -"Supprime une liste de produits d'une commande en utilisant le `product_uuid`" -" et les `attributs` fournis." +"Supprime une liste de produits d'une commande en utilisant le `product_uuid` " +"et les `attributs` fournis." #: core/docs/drf/viewsets.py:281 msgid "list all wishlists (simple view)" @@ -530,8 +527,8 @@ msgstr "" #: core/docs/drf/viewsets.py:303 msgid "rewrite some fields of an existing wishlist saving non-editables" msgstr "" -"Réécrire certains champs d'un attribut existant en sauvegardant les éléments" -" non modifiables" +"Réécrire certains champs d'un attribut existant en sauvegardant les éléments " +"non modifiables" #: core/docs/drf/viewsets.py:307 msgid "add product to wishlist" @@ -578,18 +575,29 @@ msgstr "" msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "Filtre sur une ou plusieurs paires nom/valeur d'attribut. \n" "- **Syntaxe** : `nom_attr=méthode-valeur[;attr2=méthode2-valeur2]...`\n" -"- **Méthodes** (la valeur par défaut est `icontains` si elle est omise) : `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`\n" -"- **Type de valeur** : JSON est essayé en premier (pour que vous puissiez passer des listes/dicts), `true`/`false` pour les booléens, les entiers, les flottants ; sinon traité comme une chaîne de caractères. \n" -"- **Base64** : préfixe avec `b64-` pour encoder la valeur brute en base64 de manière sûre pour l'URL. \n" +"- **Méthodes** (la valeur par défaut est `icontains` si elle est omise) : " +"`iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, " +"`istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, " +"`gt`, `gte`, `in`\n" +"- **Type de valeur** : JSON est essayé en premier (pour que vous puissiez " +"passer des listes/dicts), `true`/`false` pour les booléens, les entiers, les " +"flottants ; sinon traité comme une chaîne de caractères. \n" +"- **Base64** : préfixe avec `b64-` pour encoder la valeur brute en base64 de " +"manière sûre pour l'URL. \n" "Exemples : \n" "`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\", \"bluetooth\"]`,\n" "`b64-description=icontains-aGVhdC1jb2xk`" @@ -644,10 +652,12 @@ msgstr "(exact) Numérique ou physique" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" -"Liste de champs séparés par des virgules à trier. Préfixer avec `-` pour un tri descendant. \n" +"Liste de champs séparés par des virgules à trier. Préfixer avec `-` pour un " +"tri descendant. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" #: core/docs/drf/viewsets.py:441 @@ -778,7 +788,7 @@ msgstr "" "ajouter ou supprimer un retour d'information sur une relation commande-" "produit" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "Aucun terme de recherche n'est fourni." @@ -826,8 +836,8 @@ msgstr "Attributs" msgid "Quantity" msgstr "Quantité" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "Limace" @@ -890,961 +900,981 @@ msgstr "Niveau" msgid "Product UUID" msgstr "UUID du produit" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "Clé à rechercher ou à insérer dans la cache" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "Données à stocker dans la mémoire cache" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "Délai d'attente en secondes pour placer les données dans le cache" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "Données mises en cache" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "Données JSON camélisées provenant de l'URL demandée" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "Seuls les URL commençant par http(s):// sont autorisés." -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "Ajouter un produit à la commande" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "L'ordre {order_uuid} n'a pas été trouvé" +msgstr "Ordre {order_uuid} introuvable !" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "Supprimer un produit de la commande" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "Supprimer tous les produits de la commande" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "Acheter une commande" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "" "Veuillez fournir soit order_uuid, soit order_hr_id - les deux s'excluent " "mutuellement !" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "" "Le mauvais type provient de la méthode order.buy() : {type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "Effectuer une action sur une liste de produits dans la commande" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "Supprimer/Ajouter" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "L'action doit être soit \"ajouter\", soit \"supprimer\" !" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "" +"Effectuer une action sur une liste de produits dans la liste de souhaits" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "Veuillez indiquer la valeur de `wishlist_uuid`." + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "Wishlist {wishlist_uuid} introuvable !" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "Ajouter un produit à la commande" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "Wishlist {wishlist_uuid} introuvable" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "Supprimer un produit de la commande" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "Supprimer un produit de la commande" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "Supprimer un produit de la commande" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "Acheter une commande" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" msgstr "" "Veuillez envoyer les attributs sous la forme d'une chaîne formatée comme " "attr1=valeur1,attr2=valeur2." -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "" +"ajouter ou supprimer un retour d'information sur une relation commande-" +"produit" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "L'action doit être soit `add` soit `remove` !" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "Le produit {order_product_uuid} n'a pas été trouvé !" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "Chaîne d'adresse originale fournie par l'utilisateur" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} n'existe pas : {uuid}" +msgstr "{name} n'existe pas : {uuid} !" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "La limite doit être comprise entre 1 et 10" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - fonctionne comme un charme" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "Attributs" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "Attributs groupés" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "Groupes d'attributs" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "Catégories" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "Marques" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "Catégories" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "Markup Percentage" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "" "Quels attributs et valeurs peuvent être utilisés pour filtrer cette " "catégorie." -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." +#: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." msgstr "" "Prix minimum et maximum pour les produits de cette catégorie, s'ils sont " "disponibles." -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "Tags pour cette catégorie" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "Produits dans cette catégorie" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "Vendeurs" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "Latitude (coordonnée Y)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "Longitude (coordonnée X)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "Comment" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "Valeur d'évaluation de 1 à 10 inclus, ou 0 si elle n'est pas définie." -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "Représente le retour d'information d'un utilisateur." -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "Notifications" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "URL de téléchargement pour ce produit de la commande, le cas échéant" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "Une liste des produits commandés dans cette commande" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "Adresse de facturation" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" msgstr "" -"Adresse d'expédition pour cette commande, laisser vide si elle est identique" -" à l'adresse de facturation ou si elle n'est pas applicable" +"Adresse d'expédition pour cette commande, laisser vide si elle est identique " +"à l'adresse de facturation ou si elle n'est pas applicable" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "Prix total de la commande" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "Quantité totale de produits dans la commande" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "Tous les produits de la commande sont-ils numériques ?" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "Transactions pour cette commande" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "Commandes" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "Image URL" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "Images du produit" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "Catégorie" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "Retour d'information" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "Marque" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "Groupes d'attributs" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "Prix" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "Quantité" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "Nombre de retours d'information" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "Produits" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "Promocodes" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "Produits en vente" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "Promotions" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "Vendeur" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "Produit" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "Produits en liste de souhaits" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "Liste de souhaits" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "Produits marqués" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "Étiquettes du produit" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "Catégories marquées" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "Tags des catégories" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "Nom du projet" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "Courriel de l'entreprise" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "Nom de l'entreprise" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "Adresse de l'entreprise" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "Numéro de téléphone de l'entreprise" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "" "'email from', parfois il doit être utilisé à la place de la valeur de " "l'utilisateur de l'hôte" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "Utilisateur de l'hôte de messagerie" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "Montant maximum du paiement" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "Montant minimum pour le paiement" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "Données analytiques" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "Advertisement data" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "Configuration" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "Code langue" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "Nom de la langue" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "Drapeau linguistique, s'il existe :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "Obtenir la liste des langues prises en charge" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "Résultats de la recherche de produits" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "Résultats de la recherche de produits" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "Parent de ce groupe" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "Groupe d'attributs parent" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "Nom du groupe d'attributs" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "Groupe d'attributs" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" "Stocke les informations d'identification et les points d'extrémité " "nécessaires à la communication avec l'API du fournisseur." -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "Informations sur l'authentification" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "" "Définir la majoration pour les produits récupérés auprès de ce fournisseur" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "Pourcentage de marge du vendeur" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "Nom de ce vendeur" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "Nom du vendeur" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "Identifiant interne de l'étiquette du produit" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "Nom du jour" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "Nom convivial pour l'étiquette du produit" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "Nom d'affichage de l'étiquette" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "Étiquette du produit" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "étiquette de catégorie" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "balises de catégorie" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "Télécharger une image représentant cette catégorie" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "Image de catégorie" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "" "Définir un pourcentage de majoration pour les produits de cette catégorie" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "Parent de cette catégorie pour former une structure hiérarchique" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "Catégorie de parents" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "Nom de la catégorie" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "Donnez un nom à cette catégorie" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "Ajouter une description détaillée pour cette catégorie" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "Description de la catégorie" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "les étiquettes qui aident à décrire ou à regrouper cette catégorie" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "Priorité" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "Nom de cette marque" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "Nom de marque" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "Télécharger un logo représentant cette marque" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "Petite image de marque" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "Télécharger un grand logo représentant cette marque" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "Une grande image de marque" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "Ajouter une description détaillée de la marque" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "Description de la marque" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "Catégories facultatives auxquelles cette marque est associée" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "Catégories" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "Catégorie à laquelle appartient ce produit" - -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "Possibilité d'associer ce produit à une marque" - -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "Étiquettes permettant de décrire ou de regrouper ce produit" - -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "Indique si ce produit est livré numériquement" - -#: core/models.py:351 -msgid "is product digital" -msgstr "Le produit est-il numérique ?" - -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "Fournir un nom d'identification clair pour le produit" - -#: core/models.py:358 -msgid "product name" -msgstr "Nom du produit" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "Ajouter une description détaillée du produit" - -#: core/models.py:364 -msgid "product description" -msgstr "Description du produit" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "Numéro de pièce pour ce produit" - -#: core/models.py:372 -msgid "part number" -msgstr "Numéro de pièce" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "Catégorie de cet attribut" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "Groupe de cet attribut" - -#: core/models.py:465 -msgid "string" -msgstr "Chaîne" - -#: core/models.py:466 -msgid "integer" -msgstr "Entier" - -#: core/models.py:467 -msgid "float" -msgstr "Flotteur" - -#: core/models.py:468 -msgid "boolean" -msgstr "Booléen" - -#: core/models.py:469 -msgid "array" -msgstr "Tableau" - -#: core/models.py:470 -msgid "object" -msgstr "Objet" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "Type de la valeur de l'attribut" - -#: core/models.py:473 -msgid "value type" -msgstr "Type de valeur" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "Nom de cet attribut" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "Nom de l'attribut" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "Attribut" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "Attribut de cette valeur" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "Le produit spécifique associé à la valeur de cet attribut" - -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 -msgid "associated product" -msgstr "Produit associé" - -#: core/models.py:512 -msgid "the specific value for this attribute" -msgstr "La valeur spécifique de cet attribut" - -#: core/models.py:528 -msgid "provide alternative text for the image for accessibility" -msgstr "Fournir un texte alternatif pour l'image afin d'en faciliter l'accès" - -#: core/models.py:529 -msgid "image alt text" -msgstr "Texte alt de l'image" - -#: core/models.py:532 -msgid "upload the image file for this product" -msgstr "Télécharger le fichier image pour ce produit" - -#: core/models.py:533 core/models.py:558 -msgid "product image" -msgstr "Image du produit" - -#: core/models.py:539 -msgid "determines the order in which images are displayed" -msgstr "Détermine l'ordre d'affichage des images" - -#: core/models.py:540 -msgid "display priority" -msgstr "Priorité à l'affichage" - -#: core/models.py:545 -msgid "the product that this image represents" -msgstr "Le produit que cette image représente" - -#: core/models.py:559 -msgid "product images" -msgstr "Images du produit" - -#: core/models.py:567 -msgid "percentage discount for the selected products" -msgstr "Pourcentage de réduction pour les produits sélectionnés" - -#: core/models.py:568 -msgid "discount percentage" -msgstr "Pourcentage de réduction" - -#: core/models.py:573 -msgid "provide a unique name for this promotion" -msgstr "Donnez un nom unique à cette promotion" - -#: core/models.py:574 -msgid "promotion name" -msgstr "Nom de la promotion" - -#: core/models.py:580 -msgid "promotion description" -msgstr "Promotion description" - -#: core/models.py:585 -msgid "select which products are included in this promotion" -msgstr "Sélectionnez les produits inclus dans cette promotion" - -#: core/models.py:586 -msgid "included products" -msgstr "Produits inclus" - -#: core/models.py:590 -msgid "promotion" -msgstr "Promotion" - -#: core/models.py:605 +#: core/models.py:515 msgid "the vendor supplying this product stock" msgstr "Le vendeur qui fournit ce stock de produits" -#: core/models.py:606 +#: core/models.py:516 msgid "associated vendor" msgstr "Vendeur associé" -#: core/models.py:610 +#: core/models.py:520 msgid "final price to the customer after markups" msgstr "Prix final pour le client après majoration" -#: core/models.py:611 +#: core/models.py:521 msgid "selling price" msgstr "Prix de vente" -#: core/models.py:616 +#: core/models.py:526 msgid "the product associated with this stock entry" msgstr "Le produit associé à cette entrée de stock" -#: core/models.py:624 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "Produit associé" + +#: core/models.py:534 msgid "the price paid to the vendor for this product" msgstr "Le prix payé au vendeur pour ce produit" -#: core/models.py:625 +#: core/models.py:535 msgid "vendor purchase price" msgstr "Prix d'achat du vendeur" -#: core/models.py:629 +#: core/models.py:539 msgid "available quantity of the product in stock" msgstr "Quantité disponible du produit en stock" -#: core/models.py:630 +#: core/models.py:540 msgid "quantity in stock" msgstr "Quantité en stock" -#: core/models.py:634 +#: core/models.py:544 msgid "vendor-assigned SKU for identifying the product" msgstr "SKU attribué par le fournisseur pour identifier le produit" -#: core/models.py:635 +#: core/models.py:545 msgid "vendor sku" msgstr "UGS du vendeur" -#: core/models.py:641 +#: core/models.py:551 msgid "digital file associated with this stock if applicable" msgstr "Fichier numérique associé à ce stock, le cas échéant" -#: core/models.py:642 +#: core/models.py:552 msgid "digital file" msgstr "Fichier numérique" -#: core/models.py:651 +#: core/models.py:561 msgid "stock entries" msgstr "Entrées de stock" -#: core/models.py:660 +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "Catégorie à laquelle appartient ce produit" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "Possibilité d'associer ce produit à une marque" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "Étiquettes permettant de décrire ou de regrouper ce produit" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "Indique si ce produit est livré numériquement" + +#: core/models.py:626 +msgid "is product digital" +msgstr "Le produit est-il numérique ?" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "Fournir un nom d'identification clair pour le produit" + +#: core/models.py:633 +msgid "product name" +msgstr "Nom du produit" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "Ajouter une description détaillée du produit" + +#: core/models.py:639 +msgid "product description" +msgstr "Description du produit" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "Numéro de pièce pour ce produit" + +#: core/models.py:647 +msgid "part number" +msgstr "Numéro de pièce" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "Catégorie de cet attribut" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "Groupe de cet attribut" + +#: core/models.py:767 +msgid "string" +msgstr "Chaîne" + +#: core/models.py:768 +msgid "integer" +msgstr "Entier" + +#: core/models.py:769 +msgid "float" +msgstr "Flotteur" + +#: core/models.py:770 +msgid "boolean" +msgstr "Booléen" + +#: core/models.py:771 +msgid "array" +msgstr "Tableau" + +#: core/models.py:772 +msgid "object" +msgstr "Objet" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "Type de la valeur de l'attribut" + +#: core/models.py:775 +msgid "value type" +msgstr "Type de valeur" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "Nom de cet attribut" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "Nom de l'attribut" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "Attribut" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "Attribut de cette valeur" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "Le produit spécifique associé à la valeur de cet attribut" + +#: core/models.py:837 +msgid "the specific value for this attribute" +msgstr "La valeur spécifique de cet attribut" + +#: core/models.py:871 +msgid "provide alternative text for the image for accessibility" +msgstr "Fournir un texte alternatif pour l'image afin d'en faciliter l'accès" + +#: core/models.py:872 +msgid "image alt text" +msgstr "Texte alt de l'image" + +#: core/models.py:875 +msgid "upload the image file for this product" +msgstr "Télécharger le fichier image pour ce produit" + +#: core/models.py:876 core/models.py:901 +msgid "product image" +msgstr "Image du produit" + +#: core/models.py:882 +msgid "determines the order in which images are displayed" +msgstr "Détermine l'ordre d'affichage des images" + +#: core/models.py:883 +msgid "display priority" +msgstr "Priorité à l'affichage" + +#: core/models.py:888 +msgid "the product that this image represents" +msgstr "Le produit que cette image représente" + +#: core/models.py:902 +msgid "product images" +msgstr "Images du produit" + +#: core/models.py:943 +msgid "percentage discount for the selected products" +msgstr "Pourcentage de réduction pour les produits sélectionnés" + +#: core/models.py:944 +msgid "discount percentage" +msgstr "Pourcentage de réduction" + +#: core/models.py:949 +msgid "provide a unique name for this promotion" +msgstr "Donnez un nom unique à cette promotion" + +#: core/models.py:950 +msgid "promotion name" +msgstr "Nom de la promotion" + +#: core/models.py:956 +msgid "promotion description" +msgstr "Promotion description" + +#: core/models.py:961 +msgid "select which products are included in this promotion" +msgstr "Sélectionnez les produits inclus dans cette promotion" + +#: core/models.py:962 +msgid "included products" +msgstr "Produits inclus" + +#: core/models.py:966 +msgid "promotion" +msgstr "Promotion" + +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "Produits que l'utilisateur a marqués comme souhaités" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "Utilisateur qui possède cette liste de souhaits" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "Propriétaire de la liste de souhaits" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "Liste de souhaits" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} n'existe pas : {product_uuid}" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "Documentaire" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "Documentaires" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "Non résolu" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "Ligne d'adresse du client" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "Ligne d'adresse" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "Rue" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "District" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "Ville" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "Région" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "Code postal" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "Pays" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "Point de géolocalisation (longitude, latitude)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "Réponse JSON complète du géocodeur pour cette adresse" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "Réponse JSON stockée du service de géocodage" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "Adresse" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "Adresses" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" -msgstr "" -"Code unique utilisé par un utilisateur pour bénéficier d'une réduction" +msgstr "Code unique utilisé par un utilisateur pour bénéficier d'une réduction" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "Identifiant du code promotionnel" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" -msgstr "" -"Montant fixe de la remise appliqué si le pourcentage n'est pas utilisé" +msgstr "Montant fixe de la remise appliqué si le pourcentage n'est pas utilisé" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "Montant de l'escompte fixe" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" -msgstr "" -"Pourcentage de réduction appliqué si le montant fixe n'est pas utilisé" +msgstr "Pourcentage de réduction appliqué si le montant fixe n'est pas utilisé" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "Pourcentage de réduction" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "Date d'expiration du code promotionnel" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "Heure de fin de validité" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "Date à partir de laquelle ce code promotionnel est valable" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "Heure de début de validité" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "" -"Date à laquelle le code promotionnel a été utilisé, vide s'il n'a pas encore" -" été utilisé." +"Date à laquelle le code promotionnel a été utilisé, vide s'il n'a pas encore " +"été utilisé." -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "Horodatage de l'utilisation" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "Utilisateur assigné à ce code promo, le cas échéant" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "Utilisateur assigné" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "Code promo" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "Codes promotionnels" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." @@ -1852,144 +1882,153 @@ msgstr "" "Un seul type de remise doit être défini (montant ou pourcentage), mais pas " "les deux ni aucun des deux." -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "Le code promotionnel a déjà été utilisé" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "Type de réduction non valide pour le code promo {self.uuid}" +msgstr "Type de réduction non valide pour le code promo {self.uuid} !" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "L'adresse de facturation utilisée pour cette commande" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "Code promo optionnel appliqué à cette commande" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "Code promo appliqué" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "L'adresse de livraison utilisée pour cette commande" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "Adresse de livraison" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "Statut actuel de la commande dans son cycle de vie" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "Statut de la commande" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" "Structure JSON des notifications à afficher aux utilisateurs ; dans " "l'interface d'administration, la vue en tableau est utilisée." -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "Représentation JSON des attributs de cette commande" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "L'utilisateur qui a passé la commande" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "Utilisateur" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "L'heure à laquelle la commande a été finalisée." -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "Temps d'achat" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "Un identifiant lisible par l'homme pour la commande" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "ID lisible par l'homme" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "Commande" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "Un utilisateur ne peut avoir qu'un seul ordre en cours à la fois !" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "" -"Vous ne pouvez pas ajouter de produits à une commande qui n'est pas en " -"cours." +"Vous ne pouvez pas ajouter de produits à une commande qui n'est pas en cours." -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "Vous ne pouvez pas ajouter des produits inactifs à la commande" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "" "Vous ne pouvez pas ajouter plus de produits que ceux disponibles en stock" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "" "Vous ne pouvez pas retirer des produits d'une commande qui n'est pas en " "cours." -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "{name} n'existe pas avec la requête <{query}>" +msgstr "{name} n'existe pas avec la requête <{query}> !" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "Le code promotionnel n'existe pas" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "" "Vous ne pouvez acheter que des produits physiques dont l'adresse de " "livraison est spécifiée !" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "L'adresse n'existe pas" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "" "Vous ne pouvez pas acheter en ce moment, veuillez réessayer dans quelques " "minutes." -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "Valeur de force non valide" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "Vous ne pouvez pas acheter une commande vide !" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "" +"Vous ne pouvez pas retirer des produits d'une commande qui n'est pas en " +"cours." + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "Un utilisateur sans solde ne peut pas acheter avec un solde !" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "Insuffisance de fonds pour compléter la commande" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" @@ -1998,7 +2037,7 @@ msgstr "" "informations suivantes : nom du client, courriel du client, numéro de " "téléphone du client" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" @@ -2006,116 +2045,118 @@ msgstr "" "Méthode de paiement non valide : {payment_method} de " "{available_payment_methods} !" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "Le prix payé par le client pour ce produit au moment de l'achat" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "Prix d'achat au moment de la commande" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" -msgstr "" -"Commentaires internes pour les administrateurs sur ce produit commandé" +msgstr "Commentaires internes pour les administrateurs sur ce produit commandé" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "Commentaires internes" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "Notifications aux utilisateurs" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "Représentation JSON des attributs de cet élément" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "Attributs du produit ordonnés" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "Référence à l'ordre parent qui contient ce produit" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "Ordonnance parentale" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "Le produit spécifique associé à cette ligne de commande" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "Quantité de ce produit spécifique dans la commande" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "Quantité de produits" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "Statut actuel de ce produit dans la commande" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "Statut de la ligne de produits" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "Le produit doit être associé à une commande !" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "mauvaise action spécifiée pour le retour d'information : {action}" +msgstr "Mauvaise action spécifiée pour le retour d'information : {action} !" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "" "Vous ne pouvez pas retirer des produits d'une commande qui n'est pas en " "cours." -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "Télécharger" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "Téléchargements" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "" "Vous ne pouvez pas télécharger un bien numérique pour une commande non " "terminée." -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "Commentaires des utilisateurs sur leur expérience du produit" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "Commentaires" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "" "Fait référence au produit spécifique d'une commande sur lequel porte le " "retour d'information." -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "Produit de commande apparenté" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "Note attribuée par l'utilisateur au produit" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "Evaluation du produit" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "Retour d'information" @@ -2126,13 +2167,13 @@ msgstr "" "vous devez fournir un commentaire, une note et l'uuid du produit commandé " "pour ajouter un commentaire." -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "Erreur lors de la création du promocode : {e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2141,7 +2182,7 @@ msgid "order confirmation" msgstr "Confirmation de commande" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2158,7 +2199,8 @@ msgstr "Bonjour %(order.user.first_name)s," #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" msgstr "" "Merci pour votre commande #%(order.pk)s ! Nous avons le plaisir de vous " @@ -2166,14 +2208,14 @@ msgstr "" "dessous les détails de votre commande :" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "Total" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2193,23 +2235,23 @@ msgstr "" #: core/templates/digital_order_created_email.html:133 #, python-format msgid "best regards,
the %(config.PROJECT_NAME)s team" -msgstr "Meilleures salutations,
l'équipe de %(config.PROJECT_NAME)s" +msgstr "Meilleures salutations,
l'équipe %(config.PROJECT_NAME)s" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "Tous droits réservés" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "Commande livrée" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "Bonjour %(user_first_name)s," -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" @@ -2218,7 +2260,7 @@ msgstr "" "Nous avons traité avec succès votre commande №%(order_uuid)s ! Vous " "trouverez ci-dessous les détails de votre commande :" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2226,12 +2268,12 @@ msgstr "" "informations\n" " complémentaires" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "Valeur" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -2240,10 +2282,10 @@ msgstr "" "Si vous avez des questions, n'hésitez pas à contacter notre service " "d'assistance à %(contact_email)s." -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Meilleures salutations,
l'équipe de %(project_name)s" +msgstr "Meilleures salutations,
l'équipe %(project_name)s" #: core/templates/json_table_widget.html:5 msgid "key" @@ -2252,7 +2294,8 @@ msgstr "Clé" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" msgstr "" "Nous vous remercions pour votre commande ! Nous avons le plaisir de " @@ -2273,7 +2316,7 @@ msgstr "Votre commande sera livrée à l'adresse suivante :" #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "Meilleures salutations,
l'équipe de %(config.PROJECT_NAME)s" +msgstr "Meilleures salutations,
L'équipe %(config.PROJECT_NAME)s" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2291,30 +2334,20 @@ msgstr "Les données et le délai d'attente sont tous deux nécessaires" #: core/utils/caching.py:43 msgid "invalid timeout value, it must be between 0 and 216000 seconds" msgstr "" -"La valeur du délai d'attente n'est pas valide, elle doit être comprise entre" -" 0 et 216000 secondes." - -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model} doit être le modèle" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data} doit être un objet de liste" +"La valeur du délai d'attente n'est pas valide, elle doit être comprise entre " +"0 et 216000 secondes." #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | Nous contacter initié" +msgstr "{config.PROJECT_NAME} | nous contacter initié" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" msgstr "{config.PROJECT_NAME} | Confirmation de commande" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" msgstr "{config.PROJECT_NAME} | Commande livrée" @@ -2338,15 +2371,15 @@ msgstr "" msgid "invalid phone number format" msgstr "Format de numéro de téléphone non valide" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "Vous ne pouvez télécharger le bien numérique qu'une seule fois" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "favicon introuvable" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "Erreur de géocodage : {e}" diff --git a/core/locale/hi_IN/LC_MESSAGES/django.mo b/core/locale/hi_IN/LC_MESSAGES/django.mo index 0fc354f2..47c1f925 100644 Binary files a/core/locale/hi_IN/LC_MESSAGES/django.mo and b/core/locale/hi_IN/LC_MESSAGES/django.mo differ diff --git a/core/locale/hi_IN/LC_MESSAGES/django.po b/core/locale/hi_IN/LC_MESSAGES/django.po index 8a0441eb..f4aec1bb 100644 --- a/core/locale/hi_IN/LC_MESSAGES/django.po +++ b/core/locale/hi_IN/LC_MESSAGES/django.po @@ -5,9 +5,9 @@ # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -16,117 +16,115 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" "if set to false, this object can't be seen by users without needed permission" msgstr "" -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" msgstr "" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" +#: core/admin.py:101 +msgid "selected items have been activated." msgstr "" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" msgstr "" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." +#: core/admin.py:112 +msgid "selected items have been deactivated." msgstr "" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "" @@ -178,7 +176,7 @@ msgstr "" msgid "successful" msgstr "" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "" @@ -200,7 +198,7 @@ msgstr "" msgid "send a message to the support team" msgstr "" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "" @@ -398,7 +396,7 @@ msgid "" "transaction is initiated." msgstr "" -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "" @@ -702,7 +700,7 @@ msgstr "" msgid "add or remove feedback on an order–product relation" msgstr "" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "" @@ -750,8 +748,8 @@ msgstr "" msgid "Quantity" msgstr "" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 core/models.py:307 -#: core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "" @@ -812,1182 +810,1216 @@ msgstr "" msgid "Product UUID" msgstr "" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "" -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" msgstr "" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "" -#: core/graphene/mutations.py:326 -msgid "add a product to the wishlist" +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" msgstr "" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "" + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 #, python-brace-format msgid "wishlist {wishlist_uuid} not found" msgstr "" -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:370 +msgid "add a product to the wishlist" +msgstr "" + +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" "please send the attributes as the string formatted like attr1=value1," "attr2=value2" msgstr "" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" msgstr "" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "" -#: core/graphene/object_types.py:133 +#: core/graphene/object_types.py:135 msgid "minimum and maximum prices for products in this category, if available." msgstr "" -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "" -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "" -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" msgstr "" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "" - -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "" - -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "" - -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "" - -#: core/models.py:351 -msgid "is product digital" -msgstr "" - -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "" - -#: core/models.py:358 -msgid "product name" -msgstr "" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "" - -#: core/models.py:364 -msgid "product description" -msgstr "" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "" - -#: core/models.py:372 -msgid "part number" -msgstr "" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "" - -#: core/models.py:465 -msgid "string" -msgstr "" - -#: core/models.py:466 -msgid "integer" -msgstr "" - -#: core/models.py:467 -msgid "float" -msgstr "" - -#: core/models.py:468 -msgid "boolean" -msgstr "" - -#: core/models.py:469 -msgid "array" -msgstr "" - -#: core/models.py:470 -msgid "object" -msgstr "" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "" - -#: core/models.py:473 -msgid "value type" -msgstr "" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "" - -#: core/models.py:507 core/models.py:546 core/models.py:617 core/models.py:1361 -msgid "associated product" -msgstr "" - -#: core/models.py:512 -msgid "the specific value for this attribute" -msgstr "" - -#: core/models.py:528 -msgid "provide alternative text for the image for accessibility" -msgstr "" - -#: core/models.py:529 -msgid "image alt text" -msgstr "" - -#: core/models.py:532 -msgid "upload the image file for this product" -msgstr "" - -#: core/models.py:533 core/models.py:558 -msgid "product image" -msgstr "" - -#: core/models.py:539 -msgid "determines the order in which images are displayed" -msgstr "" - -#: core/models.py:540 -msgid "display priority" -msgstr "" - -#: core/models.py:545 -msgid "the product that this image represents" -msgstr "" - -#: core/models.py:559 -msgid "product images" -msgstr "" - -#: core/models.py:567 -msgid "percentage discount for the selected products" -msgstr "" - -#: core/models.py:568 -msgid "discount percentage" -msgstr "" - -#: core/models.py:573 -msgid "provide a unique name for this promotion" -msgstr "" - -#: core/models.py:574 -msgid "promotion name" -msgstr "" - -#: core/models.py:580 -msgid "promotion description" -msgstr "" - -#: core/models.py:585 -msgid "select which products are included in this promotion" -msgstr "" - -#: core/models.py:586 -msgid "included products" -msgstr "" - -#: core/models.py:590 -msgid "promotion" -msgstr "" - -#: core/models.py:605 +#: core/models.py:515 msgid "the vendor supplying this product stock" msgstr "" -#: core/models.py:606 +#: core/models.py:516 msgid "associated vendor" msgstr "" -#: core/models.py:610 +#: core/models.py:520 msgid "final price to the customer after markups" msgstr "" -#: core/models.py:611 +#: core/models.py:521 msgid "selling price" msgstr "" -#: core/models.py:616 +#: core/models.py:526 msgid "the product associated with this stock entry" msgstr "" -#: core/models.py:624 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "" + +#: core/models.py:534 msgid "the price paid to the vendor for this product" msgstr "" -#: core/models.py:625 +#: core/models.py:535 msgid "vendor purchase price" msgstr "" -#: core/models.py:629 +#: core/models.py:539 msgid "available quantity of the product in stock" msgstr "" -#: core/models.py:630 +#: core/models.py:540 msgid "quantity in stock" msgstr "" -#: core/models.py:634 +#: core/models.py:544 msgid "vendor-assigned SKU for identifying the product" msgstr "" -#: core/models.py:635 +#: core/models.py:545 msgid "vendor sku" msgstr "" -#: core/models.py:641 +#: core/models.py:551 msgid "digital file associated with this stock if applicable" msgstr "" -#: core/models.py:642 +#: core/models.py:552 msgid "digital file" msgstr "" -#: core/models.py:651 +#: core/models.py:561 msgid "stock entries" msgstr "" -#: core/models.py:660 -msgid "products that the user has marked as wanted" +#: core/models.py:605 +msgid "category this product belongs to" msgstr "" -#: core/models.py:668 -msgid "user who owns this wishlist" +#: core/models.py:614 +msgid "optionally associate this product with a brand" msgstr "" -#: core/models.py:669 -msgid "wishlist owner" +#: core/models.py:620 +msgid "tags that help describe or group this product" msgstr "" -#: core/models.py:677 -msgid "wishlist" +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" msgstr "" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" +#: core/models.py:626 +msgid "is product digital" msgstr "" -#: core/models.py:724 -msgid "documentary" +#: core/models.py:632 +msgid "provide a clear identifying name for the product" msgstr "" -#: core/models.py:725 -msgid "documentaries" +#: core/models.py:633 +msgid "product name" msgstr "" -#: core/models.py:735 -msgid "unresolved" +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" msgstr "" -#: core/models.py:744 -msgid "address line for the customer" +#: core/models.py:639 +msgid "product description" msgstr "" -#: core/models.py:745 -msgid "address line" +#: core/models.py:646 +msgid "part number for this product" msgstr "" -#: core/models.py:747 -msgid "street" +#: core/models.py:647 +msgid "part number" msgstr "" -#: core/models.py:748 -msgid "district" +#: core/models.py:753 +msgid "category of this attribute" msgstr "" -#: core/models.py:749 -msgid "city" -msgstr "" - -#: core/models.py:750 -msgid "region" -msgstr "" - -#: core/models.py:751 -msgid "postal code" -msgstr "" - -#: core/models.py:752 -msgid "country" -msgstr "" - -#: core/models.py:759 -msgid "geolocation point: (longitude, latitude)" -msgstr "" - -#: core/models.py:762 -msgid "full JSON response from geocoder for this address" +#: core/models.py:761 +msgid "group of this attribute" msgstr "" #: core/models.py:767 -msgid "stored JSON response from the geocoding service" +msgid "string" +msgstr "" + +#: core/models.py:768 +msgid "integer" +msgstr "" + +#: core/models.py:769 +msgid "float" +msgstr "" + +#: core/models.py:770 +msgid "boolean" +msgstr "" + +#: core/models.py:771 +msgid "array" +msgstr "" + +#: core/models.py:772 +msgid "object" +msgstr "" + +#: core/models.py:774 +msgid "type of the attribute's value" msgstr "" #: core/models.py:775 +msgid "value type" +msgstr "" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "" + +#: core/models.py:837 +msgid "the specific value for this attribute" +msgstr "" + +#: core/models.py:871 +msgid "provide alternative text for the image for accessibility" +msgstr "" + +#: core/models.py:872 +msgid "image alt text" +msgstr "" + +#: core/models.py:875 +msgid "upload the image file for this product" +msgstr "" + +#: core/models.py:876 core/models.py:901 +msgid "product image" +msgstr "" + +#: core/models.py:882 +msgid "determines the order in which images are displayed" +msgstr "" + +#: core/models.py:883 +msgid "display priority" +msgstr "" + +#: core/models.py:888 +msgid "the product that this image represents" +msgstr "" + +#: core/models.py:902 +msgid "product images" +msgstr "" + +#: core/models.py:943 +msgid "percentage discount for the selected products" +msgstr "" + +#: core/models.py:944 +msgid "discount percentage" +msgstr "" + +#: core/models.py:949 +msgid "provide a unique name for this promotion" +msgstr "" + +#: core/models.py:950 +msgid "promotion name" +msgstr "" + +#: core/models.py:956 +msgid "promotion description" +msgstr "" + +#: core/models.py:961 +msgid "select which products are included in this promotion" +msgstr "" + +#: core/models.py:962 +msgid "included products" +msgstr "" + +#: core/models.py:966 +msgid "promotion" +msgstr "" + +#: core/models.py:991 +msgid "products that the user has marked as wanted" +msgstr "" + +#: core/models.py:999 +msgid "user who owns this wishlist" +msgstr "" + +#: core/models.py:1000 +msgid "wishlist owner" +msgstr "" + +#: core/models.py:1008 +msgid "wishlist" +msgstr "" + +#: core/models.py:1075 +msgid "documentary" +msgstr "" + +#: core/models.py:1076 +msgid "documentaries" +msgstr "" + +#: core/models.py:1086 +msgid "unresolved" +msgstr "" + +#: core/models.py:1132 +msgid "address line for the customer" +msgstr "" + +#: core/models.py:1133 +msgid "address line" +msgstr "" + +#: core/models.py:1135 +msgid "street" +msgstr "" + +#: core/models.py:1136 +msgid "district" +msgstr "" + +#: core/models.py:1137 +msgid "city" +msgstr "" + +#: core/models.py:1138 +msgid "region" +msgstr "" + +#: core/models.py:1139 +msgid "postal code" +msgstr "" + +#: core/models.py:1140 +msgid "country" +msgstr "" + +#: core/models.py:1147 +msgid "geolocation point: (longitude, latitude)" +msgstr "" + +#: core/models.py:1150 +msgid "full JSON response from geocoder for this address" +msgstr "" + +#: core/models.py:1155 +msgid "stored JSON response from the geocoding service" +msgstr "" + +#: core/models.py:1163 msgid "address" msgstr "" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." msgstr "" -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" msgstr "" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "" -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "" -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" msgstr "" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "" -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "" + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" msgstr "" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" msgstr "" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" msgstr "" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "" -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "" -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "" -#: core/models.py:1490 +#: core/models.py:1970 msgid "references the specific product in an order that this feedback is about" msgstr "" -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "" @@ -1996,13 +2028,13 @@ msgid "" "you must provide a comment, rating, and order product uuid to add feedback." msgstr "" -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2011,7 +2043,7 @@ msgid "order confirmation" msgstr "" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2034,14 +2066,14 @@ msgid "" msgstr "" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2062,45 +2094,45 @@ msgid "best regards,
the %(config.PROJECT_NAME)s team" msgstr "" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "" -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" " details of your order:" msgstr "" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" msgstr "" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" " %(contact_email)s." msgstr "" -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "" @@ -2148,27 +2180,17 @@ msgstr "" msgid "invalid timeout value, it must be between 0 and 216000 seconds" msgstr "" -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" msgstr "" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" msgstr "" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" msgstr "" @@ -2190,15 +2212,15 @@ msgstr "" msgid "invalid phone number format" msgstr "" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "" diff --git a/core/locale/it_IT/LC_MESSAGES/django.mo b/core/locale/it_IT/LC_MESSAGES/django.mo index ee9a0fc6..67caf431 100644 Binary files a/core/locale/it_IT/LC_MESSAGES/django.mo and b/core/locale/it_IT/LC_MESSAGES/django.mo differ diff --git a/core/locale/it_IT/LC_MESSAGES/django.po b/core/locale/it_IT/LC_MESSAGES/django.po index 262e790d..8283b927 100644 --- a/core/locale/it_IT/LC_MESSAGES/django.po +++ b/core/locale/it_IT/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,122 +13,119 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "ID univoco" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "" "L'ID univoco viene utilizzato per identificare con certezza qualsiasi " "oggetto del database." -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "È attivo" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" +"if set to false, this object can't be seen by users without needed permission" msgstr "" -"Se impostato a false, questo oggetto non può essere visto dagli utenti senza" -" i necessari permessi." +"Se impostato a false, questo oggetto non può essere visto dagli utenti senza " +"i necessari permessi." -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "Creato" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "Quando l'oggetto è apparso per la prima volta nel database" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "Modificato" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "Quando l'oggetto è stato modificato per l'ultima volta" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "Traduzioni" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "Generale" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "Relazioni" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "Metadati" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "Timestamp" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" msgstr "Attivare il %(verbose_name_plural)s selezionato" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)s attivato con successo!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "Gli articoli selezionati sono stati attivati!" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" msgstr "Disattivare il %(verbose_name_plural)s selezionato" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "%(verbose_name_plural)s disattivato con successo." +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "Gli articoli selezionati sono stati disattivati!" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "Valore dell'attributo" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "Valori degli attributi" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "Immagine" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "Immagini" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "Stock" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "Le scorte" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "Ordina il prodotto" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "Ordinare i prodotti" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "I bambini" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "Configurazione" @@ -180,7 +177,7 @@ msgstr "Momentale" msgid "successful" msgstr "Successo" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "I/O della cache" @@ -190,7 +187,8 @@ msgid "" "apply key, data and timeout with authentication to write data to cache." msgstr "" "Applicare solo una chiave per leggere i dati consentiti dalla cache.\n" -"Applicare chiave, dati e timeout con autenticazione per scrivere dati nella cache." +"Applicare chiave, dati e timeout con autenticazione per scrivere dati nella " +"cache." #: core/docs/drf/views.py:32 msgid "get a list of supported languages" @@ -204,7 +202,7 @@ msgstr "Ottenere i parametri esponibili dell'applicazione" msgid "send a message to the support team" msgstr "Inviate un messaggio al team di assistenza" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "Richiedere un URL CORSed. È consentito solo https." @@ -247,8 +245,7 @@ msgstr "" "Riscrivere un gruppo di attributi esistente salvando i non modificabili" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" +msgid "rewrite some fields of an existing attribute group saving non-editables" msgstr "" "Riscrivere alcuni campi di un gruppo di attributi esistente salvando quelli " "non modificabili" @@ -303,8 +300,7 @@ msgstr "" "modificabili" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" +msgid "rewrite some fields of an existing attribute value saving non-editables" msgstr "" "Riscrivere alcuni campi di un valore di attributo esistente salvando i " "valori non modificabili" @@ -333,8 +329,8 @@ msgstr "" #: core/docs/drf/viewsets.py:144 msgid "rewrite some fields of an existing category saving non-editables" msgstr "" -"Riscrivere alcuni campi di una categoria esistente salvando gli elementi non" -" modificabili" +"Riscrivere alcuni campi di una categoria esistente salvando gli elementi non " +"modificabili" #: core/docs/drf/viewsets.py:151 msgid "list all orders (simple view)" @@ -348,12 +344,12 @@ msgstr "" #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" "Ricerca di sottostringhe senza distinzione di maiuscole e minuscole tra " -"human_readable_id, order_products.product.name e " -"order_products.product.partnumber" +"human_readable_id, order_products.product.name e order_products.product." +"partnumber" #: core/docs/drf/viewsets.py:165 msgid "Filter orders with buy_time >= this ISO 8601 datetime" @@ -389,9 +385,9 @@ msgstr "" #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" "Ordinare per uno dei seguenti criteri: uuid, human_readable_id, user_email, " "user, status, created, modified, buy_time, random. Prefisso con '-' per la " @@ -421,8 +417,8 @@ msgstr "" #: core/docs/drf/viewsets.py:227 msgid "rewrite some fields of an existing order saving non-editables" msgstr "" -"Riscrivere alcuni campi di una categoria esistente salvando gli elementi non" -" modificabili" +"Riscrivere alcuni campi di una categoria esistente salvando gli elementi non " +"modificabili" #: core/docs/drf/viewsets.py:231 msgid "purchase an order" @@ -435,10 +431,10 @@ msgid "" "transaction is initiated." msgstr "" "Finalizza l'acquisto dell'ordine. Se si utilizza `forza_bilancio`, " -"l'acquisto viene completato utilizzando il saldo dell'utente; se si utilizza" -" `forza_pagamento`, viene avviata una transazione." +"l'acquisto viene completato utilizzando il saldo dell'utente; se si utilizza " +"`forza_pagamento`, viene avviata una transazione." -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "acquistare un ordine senza creare un account" @@ -504,8 +500,8 @@ msgstr "Elenco di tutti gli attributi (vista semplice)" #: core/docs/drf/viewsets.py:282 msgid "for non-staff users, only their own wishlists are returned." msgstr "" -"Per gli utenti che non fanno parte del personale, vengono restituite solo le" -" loro liste dei desideri." +"Per gli utenti che non fanno parte del personale, vengono restituite solo le " +"loro liste dei desideri." #: core/docs/drf/viewsets.py:286 msgid "retrieve a single wishlist (detailed view)" @@ -578,18 +574,28 @@ msgstr "" msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "Filtrare in base a una o più coppie nome/valore dell'attributo. \n" "- **Sintassi**: `nome_attraverso=metodo-valore[;attr2=metodo2-valore2]...`\n" -"- **Metodi** (predefiniti a `icontains` se omessi): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`.\n" -"- **Tipo di valore**: JSON viene tentato per primo (in modo da poter passare liste/dict), `true`/`false` per booleani, interi, float; altrimenti viene trattato come stringa. \n" -"- **Base64**: prefisso con `b64-` per codificare in base64 il valore grezzo. \n" +"- **Metodi** (predefiniti a `icontains` se omessi): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`.\n" +"- **Tipo di valore**: JSON viene tentato per primo (in modo da poter passare " +"liste/dict), `true`/`false` per booleani, interi, float; altrimenti viene " +"trattato come stringa. \n" +"- **Base64**: prefisso con `b64-` per codificare in base64 il valore " +"grezzo. \n" "Esempi: \n" "`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\", \"bluetooth\"]`,\n" "`b64-description=icontains-aGVhdC1jb2xk`" @@ -645,10 +651,12 @@ msgstr "(esatto) Digitale e fisico" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" -"Elenco separato da virgole dei campi da ordinare. Prefisso con `-` per l'ordinamento discendente. \n" +"Elenco separato da virgole dei campi da ordinare. Prefisso con `-` per " +"l'ordinamento discendente. \n" "**Consentito:** uuid, rating, nome, slug, creato, modificato, prezzo, casuale" #: core/docs/drf/viewsets.py:441 @@ -667,8 +675,7 @@ msgstr "Creare un prodotto" #: core/docs/drf/viewsets.py:463 msgid "rewrite an existing product, preserving non-editable fields" -msgstr "" -"Riscrivere un prodotto esistente, preservando i campi non modificabili" +msgstr "Riscrivere un prodotto esistente, preservando i campi non modificabili" #: core/docs/drf/viewsets.py:478 msgid "" @@ -746,8 +753,8 @@ msgstr "" #: core/docs/drf/viewsets.py:615 msgid "rewrite some fields of an existing feedback saving non-editables" msgstr "" -"Riscrivere alcuni campi di una categoria esistente salvando gli elementi non" -" modificabili" +"Riscrivere alcuni campi di una categoria esistente salvando gli elementi non " +"modificabili" #: core/docs/drf/viewsets.py:622 msgid "list all order–product relations (simple view)" @@ -777,7 +784,7 @@ msgstr "eliminare una relazione ordine-prodotto" msgid "add or remove feedback on an order–product relation" msgstr "aggiungere o rimuovere un feedback su una relazione ordine-prodotto" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "Non è stato fornito alcun termine di ricerca." @@ -825,8 +832,8 @@ msgstr "Attributi" msgid "Quantity" msgstr "Quantità" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "Lumaca" @@ -888,219 +895,241 @@ msgstr "Livello" msgid "Product UUID" msgstr "UUID del prodotto" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "Chiave da cercare o da inserire nella cache" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "Data to store in cache" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "Timeout in secondi per l'inserimento dei dati nella cache" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "Dati in cache" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "Dati JSON camelizzati dall'URL richiesto" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "Sono consentiti solo gli URL che iniziano con http(s)://" -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "Aggiungere un prodotto all'ordine" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "Ordine {order_uuid} non trovato" +msgstr "Ordine {order_uuid} non trovato!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "Rimuovere un prodotto dall'ordine" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "Rimuovere tutti i prodotti dall'ordine" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "Acquistare un ordine" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "" "Si prega di fornire order_uuid o order_hr_id, che si escludono a vicenda!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" -msgstr "" -"Il metodo order.buy() ha fornito un tipo sbagliato: {type(instance)!s}" +msgstr "Il metodo order.buy() ha fornito un tipo sbagliato: {type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "Eseguire un'azione su un elenco di prodotti nell'ordine" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "Rimuovi/Aggiungi" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "L'azione deve essere \"aggiungere\" o \"rimuovere\"!" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "Eseguire un'azione su un elenco di prodotti nella wishlist" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "Fornire il valore `wishlist_uuid`." + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "Lista dei desideri {wishlist_uuid} non trovata!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "Aggiungere un prodotto all'ordine" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "Lista dei desideri {wishlist_uuid} non trovata" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "Rimuovere un prodotto dall'ordine" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "Rimuovere un prodotto dall'ordine" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "Rimuovere un prodotto dall'ordine" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "Acquistare un ordine" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" msgstr "" -"Inviare gli attributi come stringa formattata come " -"attr1=valore1,attr2=valore2" +"Inviare gli attributi come stringa formattata come attr1=valore1," +"attr2=valore2" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "Aggiungere o eliminare un feedback per l'ordine-prodotto" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "L'azione deve essere `add` o `remove`!" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "Prodotto dell'ordine {order_product_uuid} non trovato!" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "Stringa di indirizzo originale fornita dall'utente" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} non esiste: {uuid}" +msgstr "{name} non esiste: {uuid}!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "Il limite deve essere compreso tra 1 e 10" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch: funziona a meraviglia" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "Attributi" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "Attributi raggruppati" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "Gruppi di attributi" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "Categorie" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "Marche" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "Categorie" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "Percentuale di markup" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "" "Quali attributi e valori possono essere utilizzati per filtrare questa " "categoria." -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." +#: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." msgstr "" "Prezzi minimi e massimi per i prodotti di questa categoria, se disponibili." -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "Tag per questa categoria" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "Prodotti in questa categoria" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "Venditori" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "Latitudine (coordinata Y)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "Longitudine (coordinata X)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "Come" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "Valore di valutazione da 1 a 10, incluso, o 0 se non impostato." -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "Rappresenta il feedback di un utente." -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "Notifiche" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "URL di download per il prodotto dell'ordine, se applicabile" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "Un elenco di prodotti ordinati in questo ordine" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "Indirizzo di fatturazione" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" @@ -1108,877 +1137,881 @@ msgstr "" "Indirizzo di spedizione per questo ordine, lasciare in bianco se è uguale " "all'indirizzo di fatturazione o se non è applicabile" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "Prezzo totale dell'ordine" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "Quantità totale di prodotti in ordine" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "Tutti i prodotti sono presenti nell'ordine digitale" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "Transazioni per questo ordine" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "Ordini" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "URL immagine" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "Immagini del prodotto" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "Categoria" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "Feedback" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "Marchio" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "Gruppi di attributi" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "Prezzo" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "Quantità" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "Numero di feedback" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "Prodotti" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "Codici promozionali" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "Prodotti in vendita" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "Promozioni" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "Venditore" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "Prodotto" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "Prodotti desiderati" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "Liste dei desideri" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "Prodotti contrassegnati" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "Tag del prodotto" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "Contrassegnato dalle categorie" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "Tag delle categorie" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "Nome del progetto" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "Email aziendale" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "Nome della società" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "Indirizzo dell'azienda" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "Numero di telefono dell'azienda" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "" "'email from', a volte deve essere usato al posto del valore dell'utente host" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "Utente host dell'e-mail" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "Importo massimo per il pagamento" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "Importo minimo per il pagamento" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "Dati analitici" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "Dati pubblicitari" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "Configurazione" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "Codice lingua" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "Nome della lingua" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "Bandiera della lingua, se esiste :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "Ottenere un elenco delle lingue supportate" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "Risultati della ricerca dei prodotti" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "Risultati della ricerca dei prodotti" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "Genitore di questo gruppo" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "Gruppo di attributi padre" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "Nome del gruppo di attributi" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "Gruppo di attributi" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" "Memorizza le credenziali e gli endpoint necessari per la comunicazione API " "del fornitore." -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "Informazioni sull'autenticazione" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "Definire il markup per i prodotti recuperati da questo fornitore" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "Percentuale di ricarico del fornitore" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "Nome del fornitore" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "Nome del fornitore" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "Identificatore interno dell'etichetta del prodotto" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "Nome del tag" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "Nome intuitivo per l'etichetta del prodotto" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "Nome del tag" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "Etichetta del prodotto" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "tag categoria" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "tag di categoria" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "Caricare un'immagine che rappresenti questa categoria" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "Categoria immagine" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "" "Definire una percentuale di ricarico per i prodotti di questa categoria" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "Genitore di questa categoria per formare una struttura gerarchica" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "Categoria di genitori" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "Nome della categoria" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "Indicare un nome per questa categoria" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "Aggiungere una descrizione dettagliata per questa categoria" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "Descrizione della categoria" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "tag che aiutano a descrivere o raggruppare questa categoria" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "Priorità" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "Nome del marchio" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "Nome del marchio" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "Caricare un logo che rappresenti questo marchio" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "Immagine piccola del marchio" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "Caricare un grande logo che rappresenti questo marchio" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "Grande immagine del marchio" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "Aggiungere una descrizione dettagliata del marchio" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "Descrizione del marchio" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "Categorie opzionali a cui questo marchio è associato" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "Categorie" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "Categoria a cui appartiene questo prodotto" +#: core/models.py:515 +msgid "the vendor supplying this product stock" +msgstr "Il venditore che fornisce questo stock di prodotti" -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "Associare facoltativamente questo prodotto a un marchio" +#: core/models.py:516 +msgid "associated vendor" +msgstr "Venditore associato" -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "Tag che aiutano a descrivere o raggruppare questo prodotto" +#: core/models.py:520 +msgid "final price to the customer after markups" +msgstr "Prezzo finale al cliente dopo i ricarichi" -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "Indica se il prodotto è consegnato in formato digitale" +#: core/models.py:521 +msgid "selling price" +msgstr "Prezzo di vendita" -#: core/models.py:351 -msgid "is product digital" -msgstr "Il prodotto è digitale" +#: core/models.py:526 +msgid "the product associated with this stock entry" +msgstr "Il prodotto associato a questa voce di magazzino" -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "Fornire un nome identificativo chiaro per il prodotto" - -#: core/models.py:358 -msgid "product name" -msgstr "Nome del prodotto" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "Aggiungere una descrizione dettagliata del prodotto" - -#: core/models.py:364 -msgid "product description" -msgstr "Descrizione del prodotto" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "Numero di parte per questo prodotto" - -#: core/models.py:372 -msgid "part number" -msgstr "Numero di parte" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "Categoria di questo attributo" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "Gruppo di questo attributo" - -#: core/models.py:465 -msgid "string" -msgstr "Stringa" - -#: core/models.py:466 -msgid "integer" -msgstr "Intero" - -#: core/models.py:467 -msgid "float" -msgstr "Galleggiante" - -#: core/models.py:468 -msgid "boolean" -msgstr "Booleano" - -#: core/models.py:469 -msgid "array" -msgstr "Array" - -#: core/models.py:470 -msgid "object" -msgstr "Oggetto" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "Tipo di valore dell'attributo" - -#: core/models.py:473 -msgid "value type" -msgstr "Tipo di valore" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "Nome dell'attributo" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "Nome dell'attributo" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "Attributo" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "Attributo di questo valore" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "Il prodotto specifico associato al valore di questo attributo" - -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 msgid "associated product" msgstr "Prodotto associato" -#: core/models.py:512 +#: core/models.py:534 +msgid "the price paid to the vendor for this product" +msgstr "Il prezzo pagato al venditore per questo prodotto" + +#: core/models.py:535 +msgid "vendor purchase price" +msgstr "Prezzo di acquisto del fornitore" + +#: core/models.py:539 +msgid "available quantity of the product in stock" +msgstr "Quantità disponibile del prodotto in magazzino" + +#: core/models.py:540 +msgid "quantity in stock" +msgstr "Quantità in magazzino" + +#: core/models.py:544 +msgid "vendor-assigned SKU for identifying the product" +msgstr "SKU assegnato dal fornitore per identificare il prodotto" + +#: core/models.py:545 +msgid "vendor sku" +msgstr "SKU del venditore" + +#: core/models.py:551 +msgid "digital file associated with this stock if applicable" +msgstr "File digitale associato a questo stock, se applicabile" + +#: core/models.py:552 +msgid "digital file" +msgstr "File digitale" + +#: core/models.py:561 +msgid "stock entries" +msgstr "Voci di magazzino" + +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "Categoria a cui appartiene questo prodotto" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "Associare facoltativamente questo prodotto a un marchio" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "Tag che aiutano a descrivere o raggruppare questo prodotto" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "Indica se il prodotto è consegnato in formato digitale" + +#: core/models.py:626 +msgid "is product digital" +msgstr "Il prodotto è digitale" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "Fornire un nome identificativo chiaro per il prodotto" + +#: core/models.py:633 +msgid "product name" +msgstr "Nome del prodotto" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "Aggiungere una descrizione dettagliata del prodotto" + +#: core/models.py:639 +msgid "product description" +msgstr "Descrizione del prodotto" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "Numero di parte per questo prodotto" + +#: core/models.py:647 +msgid "part number" +msgstr "Numero di parte" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "Categoria di questo attributo" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "Gruppo di questo attributo" + +#: core/models.py:767 +msgid "string" +msgstr "Stringa" + +#: core/models.py:768 +msgid "integer" +msgstr "Intero" + +#: core/models.py:769 +msgid "float" +msgstr "Galleggiante" + +#: core/models.py:770 +msgid "boolean" +msgstr "Booleano" + +#: core/models.py:771 +msgid "array" +msgstr "Array" + +#: core/models.py:772 +msgid "object" +msgstr "Oggetto" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "Tipo di valore dell'attributo" + +#: core/models.py:775 +msgid "value type" +msgstr "Tipo di valore" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "Nome dell'attributo" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "Nome dell'attributo" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "Attributo" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "Attributo di questo valore" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "Il prodotto specifico associato al valore di questo attributo" + +#: core/models.py:837 msgid "the specific value for this attribute" msgstr "Il valore specifico per questo attributo" -#: core/models.py:528 +#: core/models.py:871 msgid "provide alternative text for the image for accessibility" msgstr "" "Fornire un testo alternativo per l'immagine ai fini dell'accessibilità." -#: core/models.py:529 +#: core/models.py:872 msgid "image alt text" msgstr "Testo alt dell'immagine" -#: core/models.py:532 +#: core/models.py:875 msgid "upload the image file for this product" msgstr "Caricare il file immagine per questo prodotto" -#: core/models.py:533 core/models.py:558 +#: core/models.py:876 core/models.py:901 msgid "product image" msgstr "Immagine del prodotto" -#: core/models.py:539 +#: core/models.py:882 msgid "determines the order in which images are displayed" msgstr "Determina l'ordine di visualizzazione delle immagini" -#: core/models.py:540 +#: core/models.py:883 msgid "display priority" msgstr "Priorità del display" -#: core/models.py:545 +#: core/models.py:888 msgid "the product that this image represents" msgstr "Il prodotto che questa immagine rappresenta" -#: core/models.py:559 +#: core/models.py:902 msgid "product images" msgstr "Immagini del prodotto" -#: core/models.py:567 +#: core/models.py:943 msgid "percentage discount for the selected products" msgstr "Percentuale di sconto per i prodotti selezionati" -#: core/models.py:568 +#: core/models.py:944 msgid "discount percentage" msgstr "Percentuale di sconto" -#: core/models.py:573 +#: core/models.py:949 msgid "provide a unique name for this promotion" msgstr "Fornite un nome unico per questa promozione" -#: core/models.py:574 +#: core/models.py:950 msgid "promotion name" msgstr "Nome della promozione" -#: core/models.py:580 +#: core/models.py:956 msgid "promotion description" msgstr "Descrizione della promozione" -#: core/models.py:585 +#: core/models.py:961 msgid "select which products are included in this promotion" msgstr "Selezionare i prodotti inclusi in questa promozione" -#: core/models.py:586 +#: core/models.py:962 msgid "included products" msgstr "Prodotti inclusi" -#: core/models.py:590 +#: core/models.py:966 msgid "promotion" msgstr "Promozione" -#: core/models.py:605 -msgid "the vendor supplying this product stock" -msgstr "Il venditore che fornisce questo stock di prodotti" - -#: core/models.py:606 -msgid "associated vendor" -msgstr "Venditore associato" - -#: core/models.py:610 -msgid "final price to the customer after markups" -msgstr "Prezzo finale al cliente dopo i ricarichi" - -#: core/models.py:611 -msgid "selling price" -msgstr "Prezzo di vendita" - -#: core/models.py:616 -msgid "the product associated with this stock entry" -msgstr "Il prodotto associato a questa voce di magazzino" - -#: core/models.py:624 -msgid "the price paid to the vendor for this product" -msgstr "Il prezzo pagato al venditore per questo prodotto" - -#: core/models.py:625 -msgid "vendor purchase price" -msgstr "Prezzo di acquisto del fornitore" - -#: core/models.py:629 -msgid "available quantity of the product in stock" -msgstr "Quantità disponibile del prodotto in magazzino" - -#: core/models.py:630 -msgid "quantity in stock" -msgstr "Quantità in magazzino" - -#: core/models.py:634 -msgid "vendor-assigned SKU for identifying the product" -msgstr "SKU assegnato dal fornitore per identificare il prodotto" - -#: core/models.py:635 -msgid "vendor sku" -msgstr "SKU del venditore" - -#: core/models.py:641 -msgid "digital file associated with this stock if applicable" -msgstr "File digitale associato a questo stock, se applicabile" - -#: core/models.py:642 -msgid "digital file" -msgstr "File digitale" - -#: core/models.py:651 -msgid "stock entries" -msgstr "Voci di magazzino" - -#: core/models.py:660 +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "Prodotti che l'utente ha contrassegnato come desiderati" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "Utente che possiede questa wishlist" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "Proprietario della lista dei desideri" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "Lista dei desideri" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} non esiste: {product_uuid}" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "Documentario" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "Documentari" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "Non risolto" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "Indirizzo del cliente" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "Linea di indirizzo" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "Via" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "Distretto" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "Città" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "Regione" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "Codice postale" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "Paese" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "Punto di geolocalizzazione(Longitudine, Latitudine)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "Risposta JSON completa di geocoder per questo indirizzo" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "Risposta JSON memorizzata dal servizio di geocodifica" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "Indirizzo" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "Indirizzi" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "Codice univoco utilizzato da un utente per riscattare uno sconto" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "Identificatore del codice promozionale" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" -msgstr "" -"Importo fisso dello sconto applicato se non si utilizza la percentuale" +msgstr "Importo fisso dello sconto applicato se non si utilizza la percentuale" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "Importo fisso dello sconto" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "Sconto percentuale applicato se l'importo fisso non viene utilizzato" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "Sconto percentuale" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "Data di scadenza del codice promozionale" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "Tempo di validità finale" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "Data a partire dalla quale il codice promozionale è valido" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "Ora di inizio validità" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "" "Timestamp in cui è stato utilizzato il codice promozionale, vuoto se non " "ancora utilizzato" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "Timestamp d'uso" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "Utente assegnato a questo codice promozionale, se applicabile" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "Utente assegnato" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "Codice promozionale" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "Codici promozionali" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." msgstr "" -"È necessario definire un solo tipo di sconto (importo o percentuale), ma non" -" entrambi o nessuno." +"È necessario definire un solo tipo di sconto (importo o percentuale), ma non " +"entrambi o nessuno." -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "Il codice promozionale è già stato utilizzato" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "Tipo di sconto non valido per il codice promozionale {self.uuid}" +msgstr "Tipo di sconto non valido per il codice promozionale {self.uuid}!" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "L'indirizzo di fatturazione utilizzato per questo ordine" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "Codice promozionale opzionale applicato a questo ordine" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "Codice promozionale applicato" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "L'indirizzo di spedizione utilizzato per questo ordine" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "Indirizzo di spedizione" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "Stato attuale dell'ordine nel suo ciclo di vita" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "Stato dell'ordine" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" "Struttura JSON delle notifiche da mostrare agli utenti; nell'interfaccia " "utente dell'amministratore viene utilizzata la visualizzazione a tabella." -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "Rappresentazione JSON degli attributi dell'ordine per questo ordine" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "L'utente che ha effettuato l'ordine" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "Utente" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "Il timestamp del momento in cui l'ordine è stato finalizzato" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "Acquista tempo" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "Un identificatore leggibile dall'uomo per l'ordine" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "ID leggibile dall'uomo" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "Ordine" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "Un utente può avere un solo ordine pendente alla volta!" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "" "Non è possibile aggiungere prodotti a un ordine che non sia in sospeso." -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "Non è possibile aggiungere all'ordine prodotti inattivi" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "" "Non è possibile aggiungere più prodotti di quelli disponibili in magazzino" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "Non è possibile rimuovere i prodotti da un ordine che non è in corso." -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "{name} non esiste con la query <{query}>." +msgstr "{name} non esiste con la query <{query}>!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "Il codice promozionale non esiste" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "" "È possibile acquistare solo prodotti fisici con indirizzo di spedizione " "specificato!" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "L'indirizzo non esiste" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "" "In questo momento non è possibile acquistare, riprovare tra qualche minuto." -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "Valore di forza non valido" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "Non è possibile acquistare un ordine vuoto!" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "Non è possibile acquistare un ordine senza un utente!" + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "Un utente senza saldo non può acquistare con il saldo!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "Fondi insufficienti per completare l'ordine" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" @@ -1987,7 +2020,7 @@ msgstr "" "seguenti informazioni: nome del cliente, e-mail del cliente, numero di " "telefono del cliente" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" @@ -1995,111 +2028,114 @@ msgstr "" "Metodo di pagamento non valido: {payment_method} da " "{available_payment_methods}!" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "" "Il prezzo pagato dal cliente per questo prodotto al momento dell'acquisto." -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "Prezzo di acquisto al momento dell'ordine" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "Commenti interni per gli amministratori su questo prodotto ordinato" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "Commenti interni" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "Notifiche degli utenti" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "Rappresentazione JSON degli attributi di questo elemento" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "Attributi del prodotto ordinati" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "Riferimento all'ordine padre che contiene questo prodotto" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "Ordine dei genitori" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "Il prodotto specifico associato a questa riga d'ordine" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "Quantità di questo prodotto specifico nell'ordine" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "Quantità di prodotto" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "Stato attuale di questo prodotto nell'ordine" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "Stato della linea di prodotti" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "L'ordine-prodotto deve avere un ordine associato!" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "azione errata specificata per il feedback: {action}" +msgstr "Azione errata specificata per il feedback: {action}!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "non è possibile dare un riscontro a un ordine non ricevuto" -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "Scaricare" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "Scaricamento" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "Non è possibile scaricare un bene digitale per un ordine non finito." -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "Commenti degli utenti sulla loro esperienza con il prodotto" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "Commenti di feedback" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "" "Riferisce il prodotto specifico in un ordine di cui si tratta il feedback." -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "Prodotto correlato all'ordine" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "Valutazione del prodotto assegnata dall'utente" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "Valutazione del prodotto" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "Feedback" @@ -2107,16 +2143,16 @@ msgstr "Feedback" msgid "" "you must provide a comment, rating, and order product uuid to add feedback." msgstr "" -"per aggiungere un feedback è necessario fornire un commento, una valutazione" -" e l'uuid del prodotto dell'ordine." +"per aggiungere un feedback è necessario fornire un commento, una valutazione " +"e l'uuid del prodotto dell'ordine." -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "Errore durante la creazione del codice promozionale: {e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2125,7 +2161,7 @@ msgid "order confirmation" msgstr "Conferma dell'ordine" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2142,7 +2178,8 @@ msgstr "Hello %(order.user.first_name)s," #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" msgstr "" "Grazie per il vostro ordine #%(order.pk)s! Siamo lieti di informarla che " @@ -2150,14 +2187,14 @@ msgstr "" "del vostro ordine:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "Totale" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2171,8 +2208,8 @@ msgid "" "if you have any questions, feel free to contact our support at\n" " %(config.EMAIL_HOST_USER)s." msgstr "" -"Per qualsiasi domanda, non esitate a contattare il nostro supporto al numero" -" %(config.EMAIL_HOST_USER)s." +"Per qualsiasi domanda, non esitate a contattare il nostro supporto al numero " +"%(config.EMAIL_HOST_USER)s." #: core/templates/digital_order_created_email.html:133 #, python-format @@ -2180,20 +2217,20 @@ msgid "best regards,
the %(config.PROJECT_NAME)s team" msgstr "Cordiali saluti,
il team %(config.PROJECT_NAME)s" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "Tutti i diritti riservati" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "Ordine consegnato" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "Hello %(user_first_name)s," -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" @@ -2202,7 +2239,7 @@ msgstr "" "Abbiamo elaborato con successo il suo ordine №%(order_uuid)s! Di seguito " "sono riportati i dettagli del suo ordine:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2210,21 +2247,21 @@ msgstr "" "ulteriori\n" " informazioni" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "Valore" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" " %(contact_email)s." msgstr "" -"Per qualsiasi domanda, non esitate a contattare il nostro supporto al numero" -" %(contact_email)s." +"Per qualsiasi domanda, non esitate a contattare il nostro supporto al numero " +"%(contact_email)s." -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Cordiali saluti,
il team %(project_name)s" @@ -2236,7 +2273,8 @@ msgstr "Chiave" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" msgstr "" "Grazie per il vostro ordine! Siamo lieti di confermare il suo acquisto. Di " @@ -2276,27 +2314,17 @@ msgid "invalid timeout value, it must be between 0 and 216000 seconds" msgstr "" "Valore di timeout non valido, deve essere compreso tra 0 e 216000 secondi." -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model} deve essere un modello" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data} deve essere un oggetto elenco" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | Contatti avviati" +msgstr "{config.PROJECT_NAME} | contattaci iniziato" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" msgstr "{config.PROJECT_NAME} | Conferma d'ordine" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" msgstr "{config.PROJECT_NAME} | Ordine consegnato" @@ -2313,22 +2341,22 @@ msgstr "Il parametro NOMINATIM_URL deve essere configurato!" #, python-brace-format msgid "image dimensions should not exceed w{max_width} x h{max_height} pixels" msgstr "" -"Le dimensioni dell'immagine non devono superare w{max_width} x h{max_height}" -" pixel" +"Le dimensioni dell'immagine non devono superare w{max_width} x h{max_height} " +"pixel" #: core/validators.py:22 msgid "invalid phone number format" msgstr "Formato del numero di telefono non valido" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "È possibile scaricare l'asset digitale una sola volta" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "favicon non trovata" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "Errore di geocodifica: {e}" diff --git a/core/locale/ja_JP/LC_MESSAGES/django.mo b/core/locale/ja_JP/LC_MESSAGES/django.mo index 683bc591..2244ee80 100644 Binary files a/core/locale/ja_JP/LC_MESSAGES/django.mo and b/core/locale/ja_JP/LC_MESSAGES/django.mo differ diff --git a/core/locale/ja_JP/LC_MESSAGES/django.po b/core/locale/ja_JP/LC_MESSAGES/django.po index 98076e69..cfec51a6 100644 --- a/core/locale/ja_JP/LC_MESSAGES/django.po +++ b/core/locale/ja_JP/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,118 +13,118 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "ユニークID" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" -msgstr "ユニークIDは、データベースオブジェクトを確実に識別するために使用されます。" +msgstr "" +"ユニークIDは、データベースオブジェクトを確実に識別するために使用されます。" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "アクティブ" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" -msgstr "falseに設定された場合、このオブジェクトは必要なパーミッションのないユーザーには見えない。" +"if set to false, this object can't be seen by users without needed permission" +msgstr "" +"falseに設定された場合、このオブジェクトは必要なパーミッションのないユーザーに" +"は見えない。" -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "作成" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "そのオブジェクトが初めてデータベースに登場した時" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "変形" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "オブジェクトの最終編集日時" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "翻訳" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "一般" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "関係" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "メタデータ" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "タイムスタンプ" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" -msgstr "選択した %(verbose_name_plural)s をアクティブにする。" +msgstr "選択した%(verbose_name_plural)sをアクティブにする" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)sは正常に起動しました!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "選択した項目がアクティブになりました!" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" -msgstr "選択された %(verbose_name_plural)s を非アクティブにする。" +msgstr "選択された%(verbose_name_plural)sを非アクティブにする" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "%(verbose_name_plural)sは正常に停止しました。" +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "選択されたアイテムは無効化されました!" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "属性値" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "属性値" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "画像" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "画像" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "在庫" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "株式" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "商品のご注文" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "商品のご注文" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "子供たち" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "コンフィグ" @@ -176,7 +176,7 @@ msgstr "モメンタル" msgid "successful" msgstr "成功" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "キャッシュI/O" @@ -186,7 +186,8 @@ msgid "" "apply key, data and timeout with authentication to write data to cache." msgstr "" "許可されたデータをキャッシュから読み出すには、キーのみを適用する。\n" -"キャッシュにデータを書き込むには、認証付きのキー、データ、タイムアウトを適用する。" +"キャッシュにデータを書き込むには、認証付きのキー、データ、タイムアウトを適用" +"する。" #: core/docs/drf/views.py:32 msgid "get a list of supported languages" @@ -200,7 +201,7 @@ msgstr "アプリケーションの公開可能なパラメータを取得する msgid "send a message to the support team" msgstr "サポートチームにメッセージを送る" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "CORSされたURLを要求する。httpsのみ許可。" @@ -216,7 +217,9 @@ msgstr "ビジネスとして注文を購入する" msgid "" "purchase an order as a business, using the provided `products` with " "`product_uuid` and `attributes`." -msgstr "提供された `product` と `product_uuid` と `attributes` を使用して、ビジネスとして注文を購入する。" +msgstr "" +"提供された `product` と `product_uuid` と `attributes` を使用して、ビジネスと" +"して注文を購入する。" #: core/docs/drf/viewsets.py:43 msgid "list all attribute groups (simple view)" @@ -239,9 +242,10 @@ msgid "rewrite an existing attribute group saving non-editables" msgstr "既存の属性グループを書き換えて、編集不可能なものを保存する。" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" -msgstr "既存の属性グループのいくつかのフィールドを書き換え、編集不可能なものを保存する。" +msgid "rewrite some fields of an existing attribute group saving non-editables" +msgstr "" +"既存の属性グループのいくつかのフィールドを書き換え、編集不可能なものを保存す" +"る。" #: core/docs/drf/viewsets.py:70 msgid "list all attributes (simple view)" @@ -265,7 +269,8 @@ msgstr "既存の属性を書き換える。" #: core/docs/drf/viewsets.py:90 msgid "rewrite some fields of an existing attribute saving non-editables" -msgstr "既存の属性のいくつかのフィールドを書き換え、編集不可能なものを保存する。" +msgstr "" +"既存の属性のいくつかのフィールドを書き換え、編集不可能なものを保存する。" #: core/docs/drf/viewsets.py:97 msgid "list all attribute values (simple view)" @@ -288,9 +293,9 @@ msgid "rewrite an existing attribute value saving non-editables" msgstr "既存の属性値を書き換える。" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" -msgstr "既存の属性値のいくつかのフィールドを書き換え、編集不可能な値を保存する。" +msgid "rewrite some fields of an existing attribute value saving non-editables" +msgstr "" +"既存の属性値のいくつかのフィールドを書き換え、編集不可能な値を保存する。" #: core/docs/drf/viewsets.py:124 msgid "list all categories (simple view)" @@ -326,10 +331,11 @@ msgstr "スタッフ以外のユーザーについては、自分の注文のみ #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" -"human_readable_id、order_products.product.name、order_products.product.partnumberの大文字小文字を区別しない部分文字列検索" +"human_readable_id、order_products.product.name、order_products.product." +"partnumberの大文字小文字を区別しない部分文字列検索" #: core/docs/drf/viewsets.py:165 msgid "Filter orders with buy_time >= this ISO 8601 datetime" @@ -349,7 +355,8 @@ msgstr "人間が読み取れる正確な注文IDによるフィルタリング" #: core/docs/drf/viewsets.py:185 msgid "Filter by user's email (case-insensitive exact match)" -msgstr "ユーザーのEメールによるフィルタリング(大文字・小文字を区別しない完全一致)" +msgstr "" +"ユーザーのEメールによるフィルタリング(大文字・小文字を区別しない完全一致)" #: core/docs/drf/viewsets.py:190 msgid "Filter by user's UUID" @@ -357,15 +364,19 @@ msgstr "ユーザーのUUIDによるフィルタリング" #: core/docs/drf/viewsets.py:195 msgid "Filter by order status (case-insensitive substring match)" -msgstr "注文ステータスによるフィルタリング(大文字と小文字を区別しない部分文字列マッチ)" +msgstr "" +"注文ステータスによるフィルタリング(大文字と小文字を区別しない部分文字列マッ" +"チ)" #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" -"uuid、human_readable_id、user_email、user、status、created、modified、buy_time、randomのいずれかによる順序。降順の場合は'-'をプレフィックスとしてつける(例:'-buy_time')。" +"uuid、human_readable_id、user_email、user、status、created、modified、" +"buy_time、randomのいずれかによる順序。降順の場合は'-'をプレフィックスとしてつ" +"ける(例:'-buy_time')。" #: core/docs/drf/viewsets.py:210 msgid "retrieve a single order (detailed view)" @@ -401,10 +412,11 @@ msgid "" "completed using the user's balance; if `force_payment` is used, a " "transaction is initiated." msgstr "" -"注文の購入を確定する。force_balance` が使用された場合、ユーザーの残高を使用して購入が完了します。 `force_payment` " -"が使用された場合、トランザクションが開始されます。" +"注文の購入を確定する。force_balance` が使用された場合、ユーザーの残高を使用し" +"て購入が完了します。 `force_payment` が使用された場合、トランザクションが開始" +"されます。" -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "アカウントを作成せずに注文を購入する" @@ -420,7 +432,8 @@ msgstr "注文に商品を追加する" msgid "" "adds a product to an order using the provided `product_uuid` and " "`attributes`." -msgstr "指定した `product_uuid` と `attributes` を使用して、商品を注文に追加する。" +msgstr "" +"指定した `product_uuid` と `attributes` を使用して、商品を注文に追加する。" #: core/docs/drf/viewsets.py:260 msgid "add a list of products to order, quantities will not count" @@ -430,7 +443,9 @@ msgstr "数量はカウントされません。" msgid "" "adds a list of products to an order using the provided `product_uuid` and " "`attributes`." -msgstr "指定された `product_uuid` と `attributes` を使用して、注文に商品のリストを追加する。" +msgstr "" +"指定された `product_uuid` と `attributes` を使用して、注文に商品のリストを追" +"加する。" #: core/docs/drf/viewsets.py:266 msgid "remove product from order" @@ -440,7 +455,9 @@ msgstr "注文から商品を削除する" msgid "" "removes a product from an order using the provided `product_uuid` and " "`attributes`." -msgstr "指定された `product_uuid` と `attributes` を使用して、注文から商品を削除する。" +msgstr "" +"指定された `product_uuid` と `attributes` を使用して、注文から商品を削除す" +"る。" #: core/docs/drf/viewsets.py:272 msgid "remove product from order, quantities will not count" @@ -450,7 +467,9 @@ msgstr "注文から商品を削除すると、数量はカウントされませ msgid "" "removes a list of products from an order using the provided `product_uuid` " "and `attributes`" -msgstr "指定された `product_uuid` と `attributes` を用いて、注文から商品のリストを削除する。" +msgstr "" +"指定された `product_uuid` と `attributes` を用いて、注文から商品のリストを削" +"除する。" #: core/docs/drf/viewsets.py:281 msgid "list all wishlists (simple view)" @@ -482,7 +501,8 @@ msgstr "既存の属性を書き換える。" #: core/docs/drf/viewsets.py:303 msgid "rewrite some fields of an existing wishlist saving non-editables" -msgstr "既存の属性のいくつかのフィールドを書き換え、編集不可能なものを保存する。" +msgstr "" +"既存の属性のいくつかのフィールドを書き換え、編集不可能なものを保存する。" #: core/docs/drf/viewsets.py:307 msgid "add product to wishlist" @@ -498,7 +518,8 @@ msgstr "ウィッシュリストから商品を削除する" #: core/docs/drf/viewsets.py:314 msgid "removes a product from an wishlist using the provided `product_uuid`" -msgstr "指定された `product_uuid` を使ってウィッシュリストから商品を削除します。" +msgstr "" +"指定された `product_uuid` を使ってウィッシュリストから商品を削除します。" #: core/docs/drf/viewsets.py:319 msgid "add many products to wishlist" @@ -506,7 +527,8 @@ msgstr "ウィッシュリストに多くの商品を追加する" #: core/docs/drf/viewsets.py:320 msgid "adds many products to an wishlist using the provided `product_uuids`" -msgstr "指定された `product_uuids` を使ってウィッシュリストに多くの商品を追加する。" +msgstr "" +"指定された `product_uuids` を使ってウィッシュリストに多くの商品を追加する。" #: core/docs/drf/viewsets.py:325 msgid "remove many products from wishlist" @@ -515,24 +537,34 @@ msgstr "注文から商品を削除する" #: core/docs/drf/viewsets.py:326 msgid "" "removes many products from an wishlist using the provided `product_uuids`" -msgstr "指定された `product_uuids` を使ってウィッシュリストから多くの商品を削除する。" +msgstr "" +"指定された `product_uuids` を使ってウィッシュリストから多くの商品を削除する。" #: core/docs/drf/viewsets.py:333 msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "1つまたは複数の属性名/値のペアでフィルタリングします。 \n" "- シンタックス**:attr_name=method-value[;attr2=method2-value2]...`。\n" -"- メソッド** (省略された場合のデフォルトは `icontains`):`iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`.\n" -"- 値の型付け**:boolean, integer, float の場合は `true`/`false`; それ以外の場合は文字列として扱う。 \n" -"- それ以外は文字列として扱われる。 **Base64**: `b64-` をプレフィックスとしてつけると、生の値を URL-safe base64-encode することができる。 \n" +"- メソッド** (省略された場合のデフォルトは `icontains`):`iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`.\n" +"- 値の型付け**:boolean, integer, float の場合は `true`/`false`; それ以外の場" +"合は文字列として扱う。 \n" +"- それ以外は文字列として扱われる。 **Base64**: `b64-` をプレフィックスとして" +"つけると、生の値を URL-safe base64-encode することができる。 \n" "例 \n" "color=exact-red`、`size=gt-10`、`features=in-[\"wifi\", \"bluetooth\"]`、\n" "b64-description=icontains-aGVhdC1jb2xk`。" @@ -587,10 +619,12 @@ msgstr "(正確には)デジタルとフィジカル" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" -"カンマ区切りの並べ替えフィールドのリスト。降順の場合は `-` をプレフィックスとしてつける。 \n" +"カンマ区切りの並べ替えフィールドのリスト。降順の場合は `-` をプレフィックスと" +"してつける。 \n" "**許可:** uuid, rating, name, slug, created, modified, price, random" #: core/docs/drf/viewsets.py:441 @@ -614,7 +648,9 @@ msgstr "編集不可能なフィールドを保持したまま、既存の製品 #: core/docs/drf/viewsets.py:478 msgid "" "update some fields of an existing product, preserving non-editable fields" -msgstr "編集不可能なフィールドを保持したまま、既存の製品の一部のフィールドを更新する。" +msgstr "" +"編集不可能なフィールドを保持したまま、既存の製品の一部のフィールドを更新す" +"る。" #: core/docs/drf/viewsets.py:493 msgid "delete a product" @@ -655,8 +691,8 @@ msgstr "オートコンプリート住所入力" #: core/docs/drf/viewsets.py:576 msgid "raw data query string, please append with data from geo-IP endpoint" msgstr "" -"docker compose exec app poetry run python manage.py deepl_translate -l en-gb" -" -l ar-ar -l cs-cz -l da-dk -l de-de -l en-us -l es-es -l fr-fr -l hi-in -l " +"docker compose exec app poetry run python manage.py deepl_translate -l en-gb " +"-l ar-ar -l cs-cz -l da-dk -l de-de -l en-us -l es-es -l fr-fr -l hi-in -l " "it-it -l ja-jp -l kk-kz -l n-nl -l pl-pl -l pt-br -l ro-ro -l ru-ru -l zh-" "hans -a core -a geo -a payments -a vibes_auth -a blog" @@ -686,7 +722,9 @@ msgstr "既存のフィードバックを書き換える。" #: core/docs/drf/viewsets.py:615 msgid "rewrite some fields of an existing feedback saving non-editables" -msgstr "既存のフィードバックのいくつかのフィールドを書き換えて、編集不可能なものを保存する。" +msgstr "" +"既存のフィードバックのいくつかのフィールドを書き換えて、編集不可能なものを保" +"存する。" #: core/docs/drf/viewsets.py:622 msgid "list all order–product relations (simple view)" @@ -716,7 +754,7 @@ msgstr "注文と商品の関係を削除する" msgid "add or remove feedback on an order–product relation" msgstr "注文と商品の関係に関するフィードバックを追加または削除する。" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "検索語はありません。" @@ -764,8 +802,8 @@ msgstr "属性" msgid "Quantity" msgstr "数量" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "スラッグ" @@ -779,7 +817,8 @@ msgstr "サブカテゴリーを含む" #: core/filters.py:147 msgid "there must be a category_uuid to use include_subcategories flag" -msgstr "include_subcategoriesフラグを使うには、category_uuidがなければならない。" +msgstr "" +"include_subcategoriesフラグを使うには、category_uuidがなければならない。" #: core/filters.py:280 msgid "Search (ID, product name or part number)" @@ -826,1200 +865,1241 @@ msgstr "レベル" msgid "Product UUID" msgstr "製品UUID" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "キャッシュを探すキー、またはキャッシュにセットするキー" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "キャッシュに保存するデータ" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "キャッシュにデータをセットするタイムアウト時間(秒" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "キャッシュ・データ" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "リクエストされたURLからキャメル化されたJSONデータ" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "http(s)://で始まるURLのみが許可されます。" -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "注文に商品を追加する" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "注文{order_uuid}が見つかりません" +msgstr "注文 {order_uuid} が見つかりません!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "注文から商品を削除する" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "注文からすべての商品を削除する" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "注文する" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "order_uuidまたはorder_hr_idを入力してください!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "order.buy()メソッドから間違った型が来た:{type(instance)!s}。" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "注文商品のリストに対してアクションを実行する" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "削除/追加" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "アクションは \"add \"か \"remove \"のどちらかでなければならない!" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "ウィッシュリストの商品リストに対してアクションを実行する" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "wishlist_uuid`の値を指定してください。" + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "ウィッシュリスト {wishlist_uuid} が見つかりません!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "注文に商品を追加する" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "ウィッシュリスト{wishlist_uuid}が見つかりません。" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "注文から商品を削除する" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "注文から商品を削除する" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "注文から商品を削除する" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "注文する" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" -msgstr "属性は、attr1=value1,attr2=value2のような形式の文字列として送信してください。" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" +msgstr "" +"属性は、attr1=value1,attr2=value2のような形式の文字列として送信してください。" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "orderproductに対するフィードバックを追加または削除する。" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "アクションは `add` または `remove` のいずれかでなければならない!" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "Orderproduct {order_product_uuid} が見つかりません!" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "ユーザーが提供したオリジナルのアドレス文字列" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} は存在しません:{uuid} は存在しません。" +msgstr "{name}は存在しません:{uuid}が存在しません!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "上限は1から10の間でなければならない" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - 魅力のように動作" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "属性" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "グループ化された属性" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "属性のグループ" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "カテゴリー" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "ブランド" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "カテゴリー" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "マークアップ率" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "このカテゴリのフィルタリングに使用できる属性と値。" -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." +#: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." msgstr "このカテゴリーの商品の最低価格と最高価格がある場合。" -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "このカテゴリのタグ" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "このカテゴリの製品" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "ベンダー" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "緯度(Y座標)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "経度(X座標)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "どのように" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "1から10までの評価値(設定されていない場合は0)。" -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "ユーザーからのフィードバックを表す。" -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "お知らせ" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "該当する場合は、この注文商品のダウンロードURLを入力してください。" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "注文商品のリスト" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "請求先住所" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" msgstr "請求先住所と同じ場合、または該当しない場合は空白にしてください。" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "この注文の合計金額" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "注文商品の総数量" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "ご注文の商品はすべてデジタルですか?" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "この注文の取引" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "受注状況" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "画像URL" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "製品画像" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "カテゴリー" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "フィードバック" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "ブランド" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "属性グループ" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "価格" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "数量" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "フィードバック数" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "製品紹介" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "プロモコード" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "販売商品" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "プロモーション" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "ベンダー" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "製品" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "ウィッシュリスト掲載商品" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "ウィッシュリスト" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "タグ別アーカイブ" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "商品タグ" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "タグ別アーカイブ" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "カテゴリー' タグ" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "プロジェクト名" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "会社Eメール" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "会社名" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "会社住所" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "会社電話番号" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "'email from' は、ホストユーザの値の代わりに使用されることがあります。" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "メールホストユーザー" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "支払限度額" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "最低支払額" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "分析データ" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "広告データ" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "構成" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "言語コード" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "言語名" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "言語フラグがある場合 :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "サポートされている言語のリストを取得する" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "製品検索結果" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "製品検索結果" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "このグループの親" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "親属性グループ" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "属性グループ名" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "属性グループ" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "ベンダーのAPI通信に必要な認証情報とエンドポイントを保存する。" -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "認証情報" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "このベンダーから取得した商品のマークアップを定義する。" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "ベンダーのマークアップ率" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "このベンダーの名前" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "ベンダー名" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "商品タグの内部タグ識別子" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "タグ名" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "商品タグのユーザーフレンドリーな名前" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "タグ表示名" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "商品タグ" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "カテゴリタグ" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "カテゴリータグ" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "このカテゴリーを表す画像をアップロードする" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "カテゴリーイメージ" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "このカテゴリの商品のマークアップ率を定義する" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "階層構造を形成するこのカテゴリの親" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "親カテゴリー" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "カテゴリー名" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "このカテゴリの名前を入力してください。" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "このカテゴリの詳細説明を追加する" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "カテゴリー説明" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "このカテゴリーを説明またはグループ化するのに役立つタグ" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "優先順位" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "ブランド名" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "ブランド名" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "このブランドを代表するロゴをアップロードする" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "小さなブランドイメージ" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "このブランドを象徴する大きなロゴをアップロードする" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "大きなブランドイメージ" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "ブランドの詳細な説明を加える" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "ブランド説明" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "このブランドが関連するオプション・カテゴリー" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "カテゴリー" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "この製品が属するカテゴリ" - -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "オプションでこの製品をブランドと関連付ける" - -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "この商品の説明やグループ分けに役立つタグ" - -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "この製品がデジタル配信されるかどうかを示す" - -#: core/models.py:351 -msgid "is product digital" -msgstr "製品はデジタルか" - -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "製品の明確な識別名を提供する" - -#: core/models.py:358 -msgid "product name" -msgstr "商品名" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "商品の詳細説明を追加する" - -#: core/models.py:364 -msgid "product description" -msgstr "商品説明" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "この製品の品番" - -#: core/models.py:372 -msgid "part number" -msgstr "品番" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "この属性のカテゴリー" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "この属性のグループ" - -#: core/models.py:465 -msgid "string" -msgstr "ストリング" - -#: core/models.py:466 -msgid "integer" -msgstr "整数" - -#: core/models.py:467 -msgid "float" -msgstr "フロート" - -#: core/models.py:468 -msgid "boolean" -msgstr "ブーリアン" - -#: core/models.py:469 -msgid "array" -msgstr "配列" - -#: core/models.py:470 -msgid "object" -msgstr "対象" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "属性値のタイプ" - -#: core/models.py:473 -msgid "value type" -msgstr "値の種類" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "この属性の名前" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "属性名" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "属性" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "この値の属性" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "この属性の値に関連する特定の製品" - -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 -msgid "associated product" -msgstr "関連製品" - -#: core/models.py:512 -msgid "the specific value for this attribute" -msgstr "この属性の具体的な値" - -#: core/models.py:528 -msgid "provide alternative text for the image for accessibility" -msgstr "アクセシビリティのために、画像に代替テキストを提供する。" - -#: core/models.py:529 -msgid "image alt text" -msgstr "画像のaltテキスト" - -#: core/models.py:532 -msgid "upload the image file for this product" -msgstr "この商品の画像ファイルをアップロードする" - -#: core/models.py:533 core/models.py:558 -msgid "product image" -msgstr "商品画像" - -#: core/models.py:539 -msgid "determines the order in which images are displayed" -msgstr "画像の表示順を決める" - -#: core/models.py:540 -msgid "display priority" -msgstr "表示優先度" - -#: core/models.py:545 -msgid "the product that this image represents" -msgstr "この画像が表す製品" - -#: core/models.py:559 -msgid "product images" -msgstr "商品画像" - -#: core/models.py:567 -msgid "percentage discount for the selected products" -msgstr "選択した商品の割引率" - -#: core/models.py:568 -msgid "discount percentage" -msgstr "割引率" - -#: core/models.py:573 -msgid "provide a unique name for this promotion" -msgstr "このプロモーションのユニークな名前を入力してください。" - -#: core/models.py:574 -msgid "promotion name" -msgstr "プロモーション名" - -#: core/models.py:580 -msgid "promotion description" -msgstr "プロモーション内容" - -#: core/models.py:585 -msgid "select which products are included in this promotion" -msgstr "キャンペーン対象商品をお選びください。" - -#: core/models.py:586 -msgid "included products" -msgstr "含まれる製品" - -#: core/models.py:590 -msgid "promotion" -msgstr "プロモーション" - -#: core/models.py:605 +#: core/models.py:515 msgid "the vendor supplying this product stock" msgstr "この製品の在庫を供給しているベンダー" -#: core/models.py:606 +#: core/models.py:516 msgid "associated vendor" msgstr "関連ベンダー" -#: core/models.py:610 +#: core/models.py:520 msgid "final price to the customer after markups" msgstr "マークアップ後の顧客への最終価格" -#: core/models.py:611 +#: core/models.py:521 msgid "selling price" msgstr "販売価格" -#: core/models.py:616 +#: core/models.py:526 msgid "the product associated with this stock entry" msgstr "このストックエントリーに関連する製品" -#: core/models.py:624 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "関連製品" + +#: core/models.py:534 msgid "the price paid to the vendor for this product" msgstr "この製品に対してベンダーに支払われた価格" -#: core/models.py:625 +#: core/models.py:535 msgid "vendor purchase price" msgstr "ベンダーの購入価格" -#: core/models.py:629 +#: core/models.py:539 msgid "available quantity of the product in stock" msgstr "在庫数" -#: core/models.py:630 +#: core/models.py:540 msgid "quantity in stock" msgstr "在庫数" -#: core/models.py:634 +#: core/models.py:544 msgid "vendor-assigned SKU for identifying the product" msgstr "製品を識別するためにベンダーが割り当てたSKU" -#: core/models.py:635 +#: core/models.py:545 msgid "vendor sku" msgstr "ベンダーのSKU" -#: core/models.py:641 +#: core/models.py:551 msgid "digital file associated with this stock if applicable" msgstr "この銘柄に関連するデジタルファイル(該当する場合" -#: core/models.py:642 +#: core/models.py:552 msgid "digital file" msgstr "デジタルファイル" -#: core/models.py:651 +#: core/models.py:561 msgid "stock entries" msgstr "ストックエントリー" -#: core/models.py:660 +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "この製品が属するカテゴリ" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "オプションでこの製品をブランドと関連付ける" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "この商品の説明やグループ分けに役立つタグ" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "この製品がデジタル配信されるかどうかを示す" + +#: core/models.py:626 +msgid "is product digital" +msgstr "製品はデジタルか" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "製品の明確な識別名を提供する" + +#: core/models.py:633 +msgid "product name" +msgstr "商品名" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "商品の詳細説明を追加する" + +#: core/models.py:639 +msgid "product description" +msgstr "商品説明" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "この製品の品番" + +#: core/models.py:647 +msgid "part number" +msgstr "品番" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "この属性のカテゴリー" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "この属性のグループ" + +#: core/models.py:767 +msgid "string" +msgstr "ストリング" + +#: core/models.py:768 +msgid "integer" +msgstr "整数" + +#: core/models.py:769 +msgid "float" +msgstr "フロート" + +#: core/models.py:770 +msgid "boolean" +msgstr "ブーリアン" + +#: core/models.py:771 +msgid "array" +msgstr "配列" + +#: core/models.py:772 +msgid "object" +msgstr "対象" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "属性値のタイプ" + +#: core/models.py:775 +msgid "value type" +msgstr "値の種類" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "この属性の名前" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "属性名" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "属性" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "この値の属性" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "この属性の値に関連する特定の製品" + +#: core/models.py:837 +msgid "the specific value for this attribute" +msgstr "この属性の具体的な値" + +#: core/models.py:871 +msgid "provide alternative text for the image for accessibility" +msgstr "アクセシビリティのために、画像に代替テキストを提供する。" + +#: core/models.py:872 +msgid "image alt text" +msgstr "画像のaltテキスト" + +#: core/models.py:875 +msgid "upload the image file for this product" +msgstr "この商品の画像ファイルをアップロードする" + +#: core/models.py:876 core/models.py:901 +msgid "product image" +msgstr "商品画像" + +#: core/models.py:882 +msgid "determines the order in which images are displayed" +msgstr "画像の表示順を決める" + +#: core/models.py:883 +msgid "display priority" +msgstr "表示優先度" + +#: core/models.py:888 +msgid "the product that this image represents" +msgstr "この画像が表す製品" + +#: core/models.py:902 +msgid "product images" +msgstr "商品画像" + +#: core/models.py:943 +msgid "percentage discount for the selected products" +msgstr "選択した商品の割引率" + +#: core/models.py:944 +msgid "discount percentage" +msgstr "割引率" + +#: core/models.py:949 +msgid "provide a unique name for this promotion" +msgstr "このプロモーションのユニークな名前を入力してください。" + +#: core/models.py:950 +msgid "promotion name" +msgstr "プロモーション名" + +#: core/models.py:956 +msgid "promotion description" +msgstr "プロモーション内容" + +#: core/models.py:961 +msgid "select which products are included in this promotion" +msgstr "キャンペーン対象商品をお選びください。" + +#: core/models.py:962 +msgid "included products" +msgstr "含まれる製品" + +#: core/models.py:966 +msgid "promotion" +msgstr "プロモーション" + +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "ユーザーが欲しいとマークした商品" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "このウィッシュリストを所有しているユーザー" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "ウィッシュリストのオーナー" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "ウィッシュリスト" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name}が存在しません:{product_uuid}が存在しません。" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "ドキュメンタリー" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "ドキュメンタリー" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "未解決" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "お客様の住所" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "住所" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "ストリート" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "地区" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "都市" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "地域" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "郵便番号" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "国名" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "ジオロケーションポイント(経度、緯度)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "この住所に対するジオコーダーからの完全なJSON応答" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "ジオコーディング・サービスからの保存されたJSONレスポンス" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "住所" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "住所" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "ユーザーが割引を利用する際に使用する固有のコード" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "プロモコード識別子" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "パーセントを使用しない場合に適用される固定割引額" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "固定割引額" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "定額を使用しない場合に適用される割引率" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "割引率" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "プロモコードの有効期限が切れるタイムスタンプ" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "終了有効時間" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "このプロモコードが有効なタイムスタンプ" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "開始有効時間" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "プロモコードが使用されたタイムスタンプ、未使用の場合は空白" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "使用タイムスタンプ" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "該当する場合、このプロモコードに割り当てられたユーザー" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "担当ユーザー" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "プロモコード" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "プロモコード" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." -msgstr "割引の種類は1つだけ(金額またはパーセント)定義されるべきで、両方またはどちらも定義してはならない。" +msgstr "" +"割引の種類は1つだけ(金額またはパーセント)定義されるべきで、両方またはどちら" +"も定義してはならない。" -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "プロモコードはすでに使用されています" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "プロモコード {self.uuid} の割引タイプが無効です。" +msgstr "プロモコード {self.uuid} の割引タイプが無効です!" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "この注文に使用される請求先住所" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "この注文に適用されるプロモコード" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "プロモーションコード適用" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "この注文に使用された配送先住所" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "配送先住所" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "ライフサイクルにおける現在の注文状況" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "注文状況" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" -msgstr "ユーザーに表示する通知のJSON構造、管理UIではテーブルビューが使用されます。" +msgstr "" +"ユーザーに表示する通知のJSON構造、管理UIではテーブルビューが使用されます。" -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "この注文の注文属性のJSON表現" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "注文を行ったユーザー" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "ユーザー" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "注文が確定したタイムスタンプ" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "時間を買う" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "オーダーの人間が読み取り可能な識別子。" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "人間が読めるID" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "オーダー" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "ユーザーは一度に1つの未決注文しか持つことができません!" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "保留中の注文以外の注文に商品を追加することはできません。" -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "アクティブでない商品を注文に追加することはできません。" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "在庫以上の商品を追加することはできません。" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "保留中の注文以外の注文から商品を削除することはできません。" -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "クエリ<{query}>で{name}が存在しません。" +msgstr "{name}はクエリ<{query}と一緒に存在しません!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "プロモコードが存在しない" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "配送先住所が指定された現物商品のみ購入可能!" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "アドレスが存在しない" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "現在ご購入いただけません。数分後にもう一度お試しください。" -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "無効なフォース値" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "空注文はできません!" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "ユーザーがいない注文は購入できない!" + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "残高のないユーザーは、残高で購入することはできない!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "注文を完了するための資金不足" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" -msgstr "ご登録がない場合はご購入いただけませんので、以下の情報をお知らせください:お客様のお名前、お客様のEメール、お客様の電話番号" +msgstr "" +"ご登録がない場合はご購入いただけませんので、以下の情報をお知らせください:お" +"客様のお名前、お客様のEメール、お客様の電話番号" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" -msgstr "支払方法が無効です:{available_payment_methods}からの{payment_method}が無効です!" +msgstr "" +"支払方法が無効です:{available_payment_methods}からの{payment_method}が無効で" +"す!" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "この商品の購入時に顧客が支払った価格" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "注文時の購入価格" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "この注文商品に関する管理者への内部コメント" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "社内コメント" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "ユーザー通知" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "このアイテムの属性のJSON表現" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "製品属性の順序" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "この商品を含む親注文への参照" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "親注文" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "この注文ラインに関連する特定の製品" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "注文に含まれる特定の商品の数量" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "製品数量" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "この商品の現在のご注文状況" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "製品ラインの状況" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "Orderproductには関連する注文がなければならない!" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "フィードバックに指定されたアクションが間違っています:{action}" +msgstr "フィードバックに指定されたアクションが間違っています:{action}です!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "受信していない注文をフィードバックすることはできません。" -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "ダウンロード" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "ダウンロード" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "未完成の注文のデジタル資産をダウンロードすることはできません。" -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "ユーザーから寄せられた製品使用体験に関するコメント" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "フィードバック・コメント" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "このフィードバックが対象としている注文の特定の製品を参照する。" -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "関連注文商品" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "ユーザーによる製品の評価" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "製品評価" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "フィードバック" #: core/serializers/utility.py:87 msgid "" "you must provide a comment, rating, and order product uuid to add feedback." -msgstr "フィードバックを追加するには、コメント、評価、および注文商品の uuid を入力する必要があります。" +msgstr "" +"フィードバックを追加するには、コメント、評価、および注文商品の uuid を入力す" +"る必要があります。" -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "プロモコード作成中にエラーが発生しました:{e!s}です。" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2028,7 +2108,7 @@ msgid "order confirmation" msgstr "ご注文の確認" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2039,25 +2119,28 @@ msgstr "ロゴ" #: core/templates/shipped_order_delivered_email.html:100 #, python-format msgid "hello %(order.user.first_name)s," -msgstr "こんにちは、%(order.user.first_name)sです、" +msgstr "こんにちは%(order.user.first_name)s、" #: core/templates/digital_order_created_email.html:102 #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" -msgstr "ご注文ありがとうございます#%(order.pk)s!ご注文を承りましたことをお知らせいたします。以下、ご注文の詳細です:" +msgstr "" +"ご注文ありがとうございます#%(order.pk)s!ご注文を承りましたことをお知らせいた" +"します。以下、ご注文の詳細です:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "合計" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2070,35 +2153,38 @@ msgstr "合計価格" msgid "" "if you have any questions, feel free to contact our support at\n" " %(config.EMAIL_HOST_USER)s." -msgstr "ご不明な点がございましたら、%(config.EMAIL_HOST_USER)sまでお気軽にお問い合わせください。" +msgstr "" +"ご不明な点がございましたら、%(config.EMAIL_HOST_USER)sまでお気軽にお問い合わ" +"せください。" #: core/templates/digital_order_created_email.html:133 #, python-format msgid "best regards,
the %(config.PROJECT_NAME)s team" -msgstr "よろしくお願いします、
%(config.PROJECT_NAME)sのチーム。" +msgstr "よろしくお願いします、
%(config.PROJECT_NAME)sチーム" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "無断複写・転載を禁じます。" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "注文の配達" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," -msgstr "こんにちは、%(user_first_name)sです、" +msgstr "こんにちは%(user_first_name)s、" -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" " details of your order:" -msgstr "ご注文の№%(order_uuid)sが正常に処理されました!以下はご注文の詳細です:" +msgstr "" +"ご注文の№%(order_uuid)sが正常に処理されました!以下はご注文の詳細です:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2106,22 +2192,24 @@ msgstr "" "追加\n" " 追加情報" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "価値" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" " %(contact_email)s." -msgstr "ご不明な点がございましたら、%(contact_email)sまでお気軽にお問い合わせください。" +msgstr "" +"ご不明な点がございましたら、%(contact_email)sまでお気軽にお問い合わせくださ" +"い。" -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "よろしくお願いします、
%(project_name)sのチーム。" +msgstr "よろしくお願いします、
%(project_name)sチーム" #: core/templates/json_table_widget.html:5 msgid "key" @@ -2130,9 +2218,12 @@ msgstr "キー" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" -msgstr "ご注文ありがとうございます!ご購入を確認させていただきました。以下、ご注文の詳細です:" +msgstr "" +"ご注文ありがとうございます!ご購入を確認させていただきました。以下、ご注文の" +"詳細です:" #: core/templates/shipped_order_created_email.html:123 #: core/templates/shipped_order_delivered_email.html:123 @@ -2148,7 +2239,7 @@ msgstr "ご注文の商品は以下の住所に配送されます:" #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "よろしくお願いします、
%(config.PROJECT_NAME)sチーム。" +msgstr "よろしくお願いします、
%(config.PROJECT_NAME)sチーム" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2167,30 +2258,20 @@ msgstr "データとタイムアウトの両方が必要" msgid "invalid timeout value, it must be between 0 and 216000 seconds" msgstr "無効なタイムアウト値です。" -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model}はモデルでなければならない" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data}はリストオブジェクトでなければならない" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | お問い合わせ| お問い合わせ" +msgstr "{config.PROJECT_NAME}|コンタクト開始| お問い合わせはこちらから" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" -msgstr "{config.PROJECT_NAME}|注文確認| 注文確認" +msgstr "{config.PROJECT_NAME}|注文確認| ご注文の確認" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" -msgstr "{config.PROJECT_NAME}|プロジェクト名| 注文の配信" +msgstr "{config.PROJECT_NAME}|ご注文は配送されますか?" #: core/utils/messages.py:3 msgid "you do not have permission to perform this action." @@ -2203,21 +2284,23 @@ msgstr "NOMINATIM_URLパラメータを設定する必要があります!" #: core/validators.py:16 #, python-brace-format msgid "image dimensions should not exceed w{max_width} x h{max_height} pixels" -msgstr "画像の寸法は、w{max_width} x h{max_height}ピクセルを超えないこと。" +msgstr "" +"画像のサイズは w{max_width} x h{max_height} ピクセルを超えないようにしてくだ" +"さい!" #: core/validators.py:22 msgid "invalid phone number format" msgstr "無効な電話番号形式" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "デジタルアセットのダウンロードは1回限りです。" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "ファビコンが見つかりません" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "ジオコーディングエラー:{e}" diff --git a/core/locale/kk_KZ/LC_MESSAGES/django.mo b/core/locale/kk_KZ/LC_MESSAGES/django.mo index 0fc354f2..47c1f925 100644 Binary files a/core/locale/kk_KZ/LC_MESSAGES/django.mo and b/core/locale/kk_KZ/LC_MESSAGES/django.mo differ diff --git a/core/locale/kk_KZ/LC_MESSAGES/django.po b/core/locale/kk_KZ/LC_MESSAGES/django.po index 8a0441eb..f4aec1bb 100644 --- a/core/locale/kk_KZ/LC_MESSAGES/django.po +++ b/core/locale/kk_KZ/LC_MESSAGES/django.po @@ -5,9 +5,9 @@ # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -16,117 +16,115 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" "if set to false, this object can't be seen by users without needed permission" msgstr "" -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" msgstr "" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" +#: core/admin.py:101 +msgid "selected items have been activated." msgstr "" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" msgstr "" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." +#: core/admin.py:112 +msgid "selected items have been deactivated." msgstr "" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "" @@ -178,7 +176,7 @@ msgstr "" msgid "successful" msgstr "" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "" @@ -200,7 +198,7 @@ msgstr "" msgid "send a message to the support team" msgstr "" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "" @@ -398,7 +396,7 @@ msgid "" "transaction is initiated." msgstr "" -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "" @@ -702,7 +700,7 @@ msgstr "" msgid "add or remove feedback on an order–product relation" msgstr "" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "" @@ -750,8 +748,8 @@ msgstr "" msgid "Quantity" msgstr "" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 core/models.py:307 -#: core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "" @@ -812,1182 +810,1216 @@ msgstr "" msgid "Product UUID" msgstr "" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "" -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" msgstr "" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "" -#: core/graphene/mutations.py:326 -msgid "add a product to the wishlist" +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" msgstr "" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "" + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 #, python-brace-format msgid "wishlist {wishlist_uuid} not found" msgstr "" -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:370 +msgid "add a product to the wishlist" +msgstr "" + +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" "please send the attributes as the string formatted like attr1=value1," "attr2=value2" msgstr "" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" msgstr "" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "" -#: core/graphene/object_types.py:133 +#: core/graphene/object_types.py:135 msgid "minimum and maximum prices for products in this category, if available." msgstr "" -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "" -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "" -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" msgstr "" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "" - -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "" - -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "" - -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "" - -#: core/models.py:351 -msgid "is product digital" -msgstr "" - -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "" - -#: core/models.py:358 -msgid "product name" -msgstr "" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "" - -#: core/models.py:364 -msgid "product description" -msgstr "" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "" - -#: core/models.py:372 -msgid "part number" -msgstr "" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "" - -#: core/models.py:465 -msgid "string" -msgstr "" - -#: core/models.py:466 -msgid "integer" -msgstr "" - -#: core/models.py:467 -msgid "float" -msgstr "" - -#: core/models.py:468 -msgid "boolean" -msgstr "" - -#: core/models.py:469 -msgid "array" -msgstr "" - -#: core/models.py:470 -msgid "object" -msgstr "" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "" - -#: core/models.py:473 -msgid "value type" -msgstr "" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "" - -#: core/models.py:507 core/models.py:546 core/models.py:617 core/models.py:1361 -msgid "associated product" -msgstr "" - -#: core/models.py:512 -msgid "the specific value for this attribute" -msgstr "" - -#: core/models.py:528 -msgid "provide alternative text for the image for accessibility" -msgstr "" - -#: core/models.py:529 -msgid "image alt text" -msgstr "" - -#: core/models.py:532 -msgid "upload the image file for this product" -msgstr "" - -#: core/models.py:533 core/models.py:558 -msgid "product image" -msgstr "" - -#: core/models.py:539 -msgid "determines the order in which images are displayed" -msgstr "" - -#: core/models.py:540 -msgid "display priority" -msgstr "" - -#: core/models.py:545 -msgid "the product that this image represents" -msgstr "" - -#: core/models.py:559 -msgid "product images" -msgstr "" - -#: core/models.py:567 -msgid "percentage discount for the selected products" -msgstr "" - -#: core/models.py:568 -msgid "discount percentage" -msgstr "" - -#: core/models.py:573 -msgid "provide a unique name for this promotion" -msgstr "" - -#: core/models.py:574 -msgid "promotion name" -msgstr "" - -#: core/models.py:580 -msgid "promotion description" -msgstr "" - -#: core/models.py:585 -msgid "select which products are included in this promotion" -msgstr "" - -#: core/models.py:586 -msgid "included products" -msgstr "" - -#: core/models.py:590 -msgid "promotion" -msgstr "" - -#: core/models.py:605 +#: core/models.py:515 msgid "the vendor supplying this product stock" msgstr "" -#: core/models.py:606 +#: core/models.py:516 msgid "associated vendor" msgstr "" -#: core/models.py:610 +#: core/models.py:520 msgid "final price to the customer after markups" msgstr "" -#: core/models.py:611 +#: core/models.py:521 msgid "selling price" msgstr "" -#: core/models.py:616 +#: core/models.py:526 msgid "the product associated with this stock entry" msgstr "" -#: core/models.py:624 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "" + +#: core/models.py:534 msgid "the price paid to the vendor for this product" msgstr "" -#: core/models.py:625 +#: core/models.py:535 msgid "vendor purchase price" msgstr "" -#: core/models.py:629 +#: core/models.py:539 msgid "available quantity of the product in stock" msgstr "" -#: core/models.py:630 +#: core/models.py:540 msgid "quantity in stock" msgstr "" -#: core/models.py:634 +#: core/models.py:544 msgid "vendor-assigned SKU for identifying the product" msgstr "" -#: core/models.py:635 +#: core/models.py:545 msgid "vendor sku" msgstr "" -#: core/models.py:641 +#: core/models.py:551 msgid "digital file associated with this stock if applicable" msgstr "" -#: core/models.py:642 +#: core/models.py:552 msgid "digital file" msgstr "" -#: core/models.py:651 +#: core/models.py:561 msgid "stock entries" msgstr "" -#: core/models.py:660 -msgid "products that the user has marked as wanted" +#: core/models.py:605 +msgid "category this product belongs to" msgstr "" -#: core/models.py:668 -msgid "user who owns this wishlist" +#: core/models.py:614 +msgid "optionally associate this product with a brand" msgstr "" -#: core/models.py:669 -msgid "wishlist owner" +#: core/models.py:620 +msgid "tags that help describe or group this product" msgstr "" -#: core/models.py:677 -msgid "wishlist" +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" msgstr "" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" +#: core/models.py:626 +msgid "is product digital" msgstr "" -#: core/models.py:724 -msgid "documentary" +#: core/models.py:632 +msgid "provide a clear identifying name for the product" msgstr "" -#: core/models.py:725 -msgid "documentaries" +#: core/models.py:633 +msgid "product name" msgstr "" -#: core/models.py:735 -msgid "unresolved" +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" msgstr "" -#: core/models.py:744 -msgid "address line for the customer" +#: core/models.py:639 +msgid "product description" msgstr "" -#: core/models.py:745 -msgid "address line" +#: core/models.py:646 +msgid "part number for this product" msgstr "" -#: core/models.py:747 -msgid "street" +#: core/models.py:647 +msgid "part number" msgstr "" -#: core/models.py:748 -msgid "district" +#: core/models.py:753 +msgid "category of this attribute" msgstr "" -#: core/models.py:749 -msgid "city" -msgstr "" - -#: core/models.py:750 -msgid "region" -msgstr "" - -#: core/models.py:751 -msgid "postal code" -msgstr "" - -#: core/models.py:752 -msgid "country" -msgstr "" - -#: core/models.py:759 -msgid "geolocation point: (longitude, latitude)" -msgstr "" - -#: core/models.py:762 -msgid "full JSON response from geocoder for this address" +#: core/models.py:761 +msgid "group of this attribute" msgstr "" #: core/models.py:767 -msgid "stored JSON response from the geocoding service" +msgid "string" +msgstr "" + +#: core/models.py:768 +msgid "integer" +msgstr "" + +#: core/models.py:769 +msgid "float" +msgstr "" + +#: core/models.py:770 +msgid "boolean" +msgstr "" + +#: core/models.py:771 +msgid "array" +msgstr "" + +#: core/models.py:772 +msgid "object" +msgstr "" + +#: core/models.py:774 +msgid "type of the attribute's value" msgstr "" #: core/models.py:775 +msgid "value type" +msgstr "" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "" + +#: core/models.py:837 +msgid "the specific value for this attribute" +msgstr "" + +#: core/models.py:871 +msgid "provide alternative text for the image for accessibility" +msgstr "" + +#: core/models.py:872 +msgid "image alt text" +msgstr "" + +#: core/models.py:875 +msgid "upload the image file for this product" +msgstr "" + +#: core/models.py:876 core/models.py:901 +msgid "product image" +msgstr "" + +#: core/models.py:882 +msgid "determines the order in which images are displayed" +msgstr "" + +#: core/models.py:883 +msgid "display priority" +msgstr "" + +#: core/models.py:888 +msgid "the product that this image represents" +msgstr "" + +#: core/models.py:902 +msgid "product images" +msgstr "" + +#: core/models.py:943 +msgid "percentage discount for the selected products" +msgstr "" + +#: core/models.py:944 +msgid "discount percentage" +msgstr "" + +#: core/models.py:949 +msgid "provide a unique name for this promotion" +msgstr "" + +#: core/models.py:950 +msgid "promotion name" +msgstr "" + +#: core/models.py:956 +msgid "promotion description" +msgstr "" + +#: core/models.py:961 +msgid "select which products are included in this promotion" +msgstr "" + +#: core/models.py:962 +msgid "included products" +msgstr "" + +#: core/models.py:966 +msgid "promotion" +msgstr "" + +#: core/models.py:991 +msgid "products that the user has marked as wanted" +msgstr "" + +#: core/models.py:999 +msgid "user who owns this wishlist" +msgstr "" + +#: core/models.py:1000 +msgid "wishlist owner" +msgstr "" + +#: core/models.py:1008 +msgid "wishlist" +msgstr "" + +#: core/models.py:1075 +msgid "documentary" +msgstr "" + +#: core/models.py:1076 +msgid "documentaries" +msgstr "" + +#: core/models.py:1086 +msgid "unresolved" +msgstr "" + +#: core/models.py:1132 +msgid "address line for the customer" +msgstr "" + +#: core/models.py:1133 +msgid "address line" +msgstr "" + +#: core/models.py:1135 +msgid "street" +msgstr "" + +#: core/models.py:1136 +msgid "district" +msgstr "" + +#: core/models.py:1137 +msgid "city" +msgstr "" + +#: core/models.py:1138 +msgid "region" +msgstr "" + +#: core/models.py:1139 +msgid "postal code" +msgstr "" + +#: core/models.py:1140 +msgid "country" +msgstr "" + +#: core/models.py:1147 +msgid "geolocation point: (longitude, latitude)" +msgstr "" + +#: core/models.py:1150 +msgid "full JSON response from geocoder for this address" +msgstr "" + +#: core/models.py:1155 +msgid "stored JSON response from the geocoding service" +msgstr "" + +#: core/models.py:1163 msgid "address" msgstr "" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." msgstr "" -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" msgstr "" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "" -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "" -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" msgstr "" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "" -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "" + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" msgstr "" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" msgstr "" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" msgstr "" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "" -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "" -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "" -#: core/models.py:1490 +#: core/models.py:1970 msgid "references the specific product in an order that this feedback is about" msgstr "" -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "" @@ -1996,13 +2028,13 @@ msgid "" "you must provide a comment, rating, and order product uuid to add feedback." msgstr "" -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2011,7 +2043,7 @@ msgid "order confirmation" msgstr "" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2034,14 +2066,14 @@ msgid "" msgstr "" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2062,45 +2094,45 @@ msgid "best regards,
the %(config.PROJECT_NAME)s team" msgstr "" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "" -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" " details of your order:" msgstr "" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" msgstr "" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" " %(contact_email)s." msgstr "" -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "" @@ -2148,27 +2180,17 @@ msgstr "" msgid "invalid timeout value, it must be between 0 and 216000 seconds" msgstr "" -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" msgstr "" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" msgstr "" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" msgstr "" @@ -2190,15 +2212,15 @@ msgstr "" msgid "invalid phone number format" msgstr "" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "" diff --git a/core/locale/nl_NL/LC_MESSAGES/django.mo b/core/locale/nl_NL/LC_MESSAGES/django.mo index a8a6ee7b..f411d933 100644 Binary files a/core/locale/nl_NL/LC_MESSAGES/django.mo and b/core/locale/nl_NL/LC_MESSAGES/django.mo differ diff --git a/core/locale/nl_NL/LC_MESSAGES/django.po b/core/locale/nl_NL/LC_MESSAGES/django.po index 1827f846..ce5cc34e 100644 --- a/core/locale/nl_NL/LC_MESSAGES/django.po +++ b/core/locale/nl_NL/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,120 +13,117 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "Uniek ID" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "Unieke ID wordt gebruikt om elk databaseobject te identificeren" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "Is actief" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" +"if set to false, this object can't be seen by users without needed permission" msgstr "" "Als false is ingesteld, kan dit object niet worden gezien door gebruikers " "zonder de benodigde toestemming" -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "Gemaakt" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "Wanneer het object voor het eerst in de database verscheen" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "Gewijzigd" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "Wanneer het object voor het laatst bewerkt is" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "Vertalingen" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "Algemeen" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "Relaties" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "Metagegevens" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "Tijdstempels" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" msgstr "Activeer geselecteerde %(verbose_name_plural)s" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)s met succes geactiveerd!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "Geselecteerde items zijn geactiveerd!" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" -msgstr "Deactiveer geselecteerde %(verbose_name_plural)s" +msgstr "Deactiveer geselecteerd %(verbose_name_plural)s" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "%(verbose_name_plural)s met succes gedeactiveerd." +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "Geselecteerde items zijn gedeactiveerd!" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "Attribuut Waarde" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "Attribuutwaarden" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "Afbeelding" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "Afbeeldingen" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "Voorraad" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "Aandelen" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "Product bestellen" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "Producten bestellen" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "Kinderen" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "Config" @@ -178,7 +175,7 @@ msgstr "Momental" msgid "successful" msgstr "Succesvol" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "Cache I/O" @@ -188,7 +185,8 @@ msgid "" "apply key, data and timeout with authentication to write data to cache." msgstr "" "Alleen een sleutel gebruiken om toegestane gegevens uit de cache te lezen.\n" -"Sleutel, gegevens en time-out met verificatie toepassen om gegevens naar de cache te schrijven." +"Sleutel, gegevens en time-out met verificatie toepassen om gegevens naar de " +"cache te schrijven." #: core/docs/drf/views.py:32 msgid "get a list of supported languages" @@ -202,7 +200,7 @@ msgstr "Verkrijg de blootstelbare parameters van de applicatie" msgid "send a message to the support team" msgstr "Stuur een bericht naar het ondersteuningsteam" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "Vraag een CORSed URL op. Alleen https toegestaan." @@ -246,8 +244,7 @@ msgstr "" "opslaan" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" +msgid "rewrite some fields of an existing attribute group saving non-editables" msgstr "" "Enkele velden van een bestaande attribuutgroep herschrijven door niet-" "wijzigbare velden op te slaan" @@ -302,8 +299,7 @@ msgstr "" "attributen worden opgeslagen" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" +msgid "rewrite some fields of an existing attribute value saving non-editables" msgstr "" "Herschrijf sommige velden van een bestaande attribuutwaarde door niet-" "wijzigbare velden op te slaan" @@ -341,16 +337,15 @@ msgstr "Alle categorieën weergeven (eenvoudige weergave)" #: core/docs/drf/viewsets.py:152 msgid "for non-staff users, only their own orders are returned." msgstr "" -"Voor niet-personeelsleden worden alleen hun eigen bestellingen " -"geretourneerd." +"Voor niet-personeelsleden worden alleen hun eigen bestellingen geretourneerd." #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" -"Hoofdlettergevoelig substring zoeken in human_readable_id, " -"order_products.product.name en order_products.product.partnumber" +"Hoofdlettergevoelig substring zoeken in human_readable_id, order_products." +"product.name en order_products.product.partnumber" #: core/docs/drf/viewsets.py:165 msgid "Filter orders with buy_time >= this ISO 8601 datetime" @@ -383,13 +378,13 @@ msgstr "Filter op bestelstatus (hoofdlettergevoelige substringmatch)" #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" "Sorteer op een van: uuid, human_readable_id, user_email, gebruiker, status, " -"gemaakt, gewijzigd, buy_time, willekeurig. Voorvoegsel met '-' voor aflopend" -" (bijv. '-buy_time')." +"gemaakt, gewijzigd, buy_time, willekeurig. Voorvoegsel met '-' voor aflopend " +"(bijv. '-buy_time')." #: core/docs/drf/viewsets.py:210 msgid "retrieve a single order (detailed view)" @@ -431,15 +426,14 @@ msgstr "" "wordt de aankoop afgerond met het saldo van de gebruiker; als " "`force_payment` wordt gebruikt, wordt een transactie gestart." -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "een bestelling kopen zonder een account aan te maken" #: core/docs/drf/viewsets.py:246 msgid "finalizes the order purchase for a non-registered user." msgstr "" -"Rondt de aankoop van de bestelling af voor een niet-geregistreerde " -"gebruiker." +"Rondt de aankoop van de bestelling af voor een niet-geregistreerde gebruiker." #: core/docs/drf/viewsets.py:254 msgid "add product to order" @@ -573,18 +567,28 @@ msgstr "" msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "Filter op een of meer attribuutnaam-/waardeparen. \n" "- **Syntaxis**: `attr_name=methode-waarde[;attr2=methode2-waarde2]...`\n" -"- **Methodes** (standaard op `icontains` indien weggelaten): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`.\n" -"- Waarde typen**: JSON wordt eerst geprobeerd (zodat je lijsten/dicten kunt doorgeven), `true`/`false` voor booleans, integers, floats; anders behandeld als string. \n" -"- **Base64**: prefix met `b64-` om URL-veilige base64-encodering van de ruwe waarde. \n" +"- **Methodes** (standaard op `icontains` indien weggelaten): `iexact`, " +"`exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, " +"`endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`.\n" +"- Waarde typen**: JSON wordt eerst geprobeerd (zodat je lijsten/dicten kunt " +"doorgeven), `true`/`false` voor booleans, integers, floats; anders behandeld " +"als string. \n" +"- **Base64**: prefix met `b64-` om URL-veilige base64-encodering van de ruwe " +"waarde. \n" "Voorbeelden: \n" "`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`,\n" "`b64-description=icontains-aGVhdC1jb2xk`." @@ -639,11 +643,14 @@ msgstr "(exact) Digitaal vs. fysiek" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" -"Door komma's gescheiden lijst van velden om op te sorteren. Voorvoegsel met `-` voor aflopend. \n" -"**Toegestaan:** uuid, beoordeling, naam, slug, gemaakt, gewijzigd, prijs, willekeurig" +"Door komma's gescheiden lijst van velden om op te sorteren. Voorvoegsel met " +"`-` voor aflopend. \n" +"**Toegestaan:** uuid, beoordeling, naam, slug, gemaakt, gewijzigd, prijs, " +"willekeurig" #: core/docs/drf/viewsets.py:441 msgid "retrieve a single product (detailed view)" @@ -751,8 +758,7 @@ msgstr "alle order-productrelaties weergeven (eenvoudige weergave)" #: core/docs/drf/viewsets.py:629 msgid "retrieve a single order–product relation (detailed view)" -msgstr "" -"een enkele bestelling-productrelatie ophalen (gedetailleerde weergave)" +msgstr "een enkele bestelling-productrelatie ophalen (gedetailleerde weergave)" #: core/docs/drf/viewsets.py:636 msgid "create a new order–product relation" @@ -774,7 +780,7 @@ msgstr "een order-productrelatie verwijderen" msgid "add or remove feedback on an order–product relation" msgstr "feedback toevoegen of verwijderen op een order-productrelatie" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "Geen zoekterm opgegeven." @@ -822,8 +828,8 @@ msgstr "Attributen" msgid "Quantity" msgstr "Hoeveelheid" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "Slak" @@ -885,217 +891,240 @@ msgstr "Niveau" msgid "Product UUID" msgstr "Product UUID" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "Sleutel om te zoeken of te plaatsen in de cache" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "Gegevens om op te slaan in de cache" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "Time-out in seconden om de gegevens in de cache te plaatsen" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "Gecachte gegevens" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "Camelized JSON-gegevens van de opgevraagde URL" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "Alleen URL's die beginnen met http(s):// zijn toegestaan" -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "Een product aan de bestelling toevoegen" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "Order {order_uuid} niet gevonden" +msgstr "Bestelling {order_uuid} niet gevonden!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "Een product uit de bestelling verwijderen" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "Alle producten uit de bestelling verwijderen" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "Een bestelling kopen" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "Geef order_uuid of order_hr_id - wederzijds exclusief!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "Verkeerd type kwam uit order.buy() methode: {type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "Een actie uitvoeren op een lijst met producten in de bestelling" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "Verwijderen/toevoegen" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "De actie moet \"toevoegen\" of \"verwijderen\" zijn!" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "Een actie uitvoeren op een lijst met producten in het verlanglijstje" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "Geef de waarde `wishlist_uuid` op." + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "wens {wishlist_uuid} niet gevonden!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "Een product aan de bestelling toevoegen" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "Verlanglijst {wishlist_uuid} niet gevonden" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "Een product uit de bestelling verwijderen" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "Een product uit de bestelling verwijderen" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "Een product uit de bestelling verwijderen" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "Een bestelling kopen" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" msgstr "" "Stuur de attributen als de string opgemaakt als attr1=waarde1,attr2=waarde2" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "Feedback toevoegen of verwijderen voor het orderproduct" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "De actie moet `toevoegen` of `verwijderen` zijn!" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "Orderproduct {order_product_uuid} niet gevonden!" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "Originele adresstring geleverd door de gebruiker" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} bestaat niet: {uuid}" +msgstr "{name} bestaat niet: {uuid}!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "Limiet moet tussen 1 en 10 liggen" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - werkt als een charme" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "Attributen" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "Gegroepeerde kenmerken" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "Groepen van kenmerken" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "Categorieën" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "Merken" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "Categorieën" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "Opwaarderingspercentage" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "" "Welke attributen en waarden kunnen worden gebruikt om deze categorie te " "filteren." -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." +#: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." msgstr "" "Minimale en maximale prijzen voor producten in deze categorie, indien " "beschikbaar." -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "Tags voor deze categorie" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "Producten in deze categorie" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "Verkopers" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "Breedtegraad (Y-coördinaat)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "Lengtegraad (X-coördinaat)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "Hoe" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "Waarderingswaarde van 1 tot en met 10, of 0 indien niet ingesteld." -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "Vertegenwoordigt feedback van een gebruiker." -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "Meldingen" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "Download url voor dit bestelproduct indien van toepassing" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "Een lijst met bestelde producten in deze bestelling" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "Factuuradres" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" @@ -1103,879 +1132,885 @@ msgstr "" "Verzendadres voor deze bestelling, leeg laten als dit hetzelfde is als het " "factuuradres of als dit niet van toepassing is" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "Totale prijs van deze bestelling" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "Totale hoeveelheid producten in bestelling" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "Zijn alle producten in de bestelling digitaal" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "Transacties voor deze bestelling" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "Bestellingen" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "Afbeelding URL" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "Afbeeldingen van het product" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "Categorie" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "Reacties" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "Merk" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "Attribuutgroepen" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "Prijs" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "Hoeveelheid" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "Aantal terugkoppelingen" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "Producten" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "Promocodes" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "Producten te koop" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "Promoties" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "Verkoper" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "Product" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "Gewenste producten" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "Verlanglijst" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "Getagde producten" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "Product tags" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "Getagde categorieën" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "Categorieën' tags" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "Naam project" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "Bedrijf E-mail" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "Bedrijfsnaam" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "Adres" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "Telefoonnummer bedrijf" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "" "e-mail van', soms moet deze worden gebruikt in plaats van de " "hostgebruikerswaarde" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "Gebruiker e-mail hosten" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "Maximumbedrag voor betaling" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "Minimumbedrag voor betaling" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "Analytics-gegevens" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "Advertentiegegevens" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "Configuratie" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "Taalcode" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "Naam van de taal" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "Taalvlag, indien aanwezig :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "Een lijst met ondersteunde talen opvragen" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "Producten zoekresultaten" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "Zoekresultaten" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "Ouder van deze groep" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "Ouderattribuutgroep" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "Naam attribuutgroep" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "Attribuutgroep" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" "Slaat referenties en eindpunten op die vereist zijn voor API-communicatie " "van de verkoper" -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "Authenticatie-info" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "" "Definieer de opmaak voor producten die zijn opgehaald bij deze leverancier" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "Verkoper winstpercentage" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "Naam van deze verkoper" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "Naam verkoper" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "Interne tagidentifier voor de producttag" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "Tag naam" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "Gebruiksvriendelijke naam voor de producttag" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "Tag weergavenaam" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "Productlabel" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "categorie tag" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "categorie tags" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "Upload een afbeelding die deze categorie vertegenwoordigt" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "Categorie afbeelding" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "Definieer een toeslagpercentage voor producten in deze categorie" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "Ouder van deze categorie om een hiërarchische structuur te vormen" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "Oudercategorie" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "Naam categorie" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "Geef deze categorie een naam" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "Voeg een gedetailleerde beschrijving toe voor deze categorie" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "Categorie beschrijving" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "tags die deze categorie helpen beschrijven of groeperen" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "Prioriteit" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "Naam van dit merk" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "Merknaam" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "Upload een logo dat dit merk vertegenwoordigt" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "Klein merkimago" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "Upload een groot logo dat dit merk vertegenwoordigt" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "Groot merkimago" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "Een gedetailleerde beschrijving van het merk toevoegen" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "Merknaam" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "Optionele categorieën waarmee dit merk wordt geassocieerd" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "Categorieën" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "Categorie waartoe dit product behoort" - -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "Dit product optioneel koppelen aan een merk" - -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "Tags die dit product helpen beschrijven of groeperen" - -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "Geeft aan of dit product digitaal wordt geleverd" - -#: core/models.py:351 -msgid "is product digital" -msgstr "Is product digitaal" - -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "Zorg voor een duidelijke identificerende naam voor het product" - -#: core/models.py:358 -msgid "product name" -msgstr "Naam product" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "Voeg een gedetailleerde beschrijving van het product toe" - -#: core/models.py:364 -msgid "product description" -msgstr "Productbeschrijving" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "Onderdeelnummer voor dit product" - -#: core/models.py:372 -msgid "part number" -msgstr "Onderdeelnummer" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "Categorie van dit kenmerk" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "Groep van dit kenmerk" - -#: core/models.py:465 -msgid "string" -msgstr "String" - -#: core/models.py:466 -msgid "integer" -msgstr "Integer" - -#: core/models.py:467 -msgid "float" -msgstr "Vlotter" - -#: core/models.py:468 -msgid "boolean" -msgstr "Booleaans" - -#: core/models.py:469 -msgid "array" -msgstr "Array" - -#: core/models.py:470 -msgid "object" -msgstr "Object" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "Type waarde van het kenmerk" - -#: core/models.py:473 -msgid "value type" -msgstr "Waardetype" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "Naam van dit kenmerk" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "Naam attribuut" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "Attribuut" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "Attribuut van deze waarde" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "Het specifieke product geassocieerd met de waarde van dit kenmerk" - -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 -msgid "associated product" -msgstr "Bijbehorend product" - -#: core/models.py:512 -msgid "the specific value for this attribute" -msgstr "De specifieke waarde voor dit kenmerk" - -#: core/models.py:528 -msgid "provide alternative text for the image for accessibility" -msgstr "Geef alternatieve tekst voor de afbeelding voor toegankelijkheid" - -#: core/models.py:529 -msgid "image alt text" -msgstr "Alt-tekst afbeelding" - -#: core/models.py:532 -msgid "upload the image file for this product" -msgstr "Upload het afbeeldingsbestand voor dit product" - -#: core/models.py:533 core/models.py:558 -msgid "product image" -msgstr "Product afbeelding" - -#: core/models.py:539 -msgid "determines the order in which images are displayed" -msgstr "Bepaalt de volgorde waarin afbeeldingen worden weergegeven" - -#: core/models.py:540 -msgid "display priority" -msgstr "Prioriteit weergeven" - -#: core/models.py:545 -msgid "the product that this image represents" -msgstr "Het product dat deze afbeelding vertegenwoordigt" - -#: core/models.py:559 -msgid "product images" -msgstr "Product afbeeldingen" - -#: core/models.py:567 -msgid "percentage discount for the selected products" -msgstr "Kortingspercentage voor de geselecteerde producten" - -#: core/models.py:568 -msgid "discount percentage" -msgstr "Kortingspercentage" - -#: core/models.py:573 -msgid "provide a unique name for this promotion" -msgstr "Geef deze promotie een unieke naam" - -#: core/models.py:574 -msgid "promotion name" -msgstr "Naam promotie" - -#: core/models.py:580 -msgid "promotion description" -msgstr "Promotie beschrijving" - -#: core/models.py:585 -msgid "select which products are included in this promotion" -msgstr "Selecteer welke producten onder deze promotie vallen" - -#: core/models.py:586 -msgid "included products" -msgstr "Meegeleverde producten" - -#: core/models.py:590 -msgid "promotion" -msgstr "Promotie" - -#: core/models.py:605 +#: core/models.py:515 msgid "the vendor supplying this product stock" msgstr "De verkoper die dit product levert" -#: core/models.py:606 +#: core/models.py:516 msgid "associated vendor" msgstr "Geassocieerde verkoper" -#: core/models.py:610 +#: core/models.py:520 msgid "final price to the customer after markups" msgstr "Eindprijs voor de klant na winstmarges" -#: core/models.py:611 +#: core/models.py:521 msgid "selling price" msgstr "Verkoopprijs" -#: core/models.py:616 +#: core/models.py:526 msgid "the product associated with this stock entry" msgstr "Het product dat bij deze voorraadvermelding hoort" -#: core/models.py:624 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "Bijbehorend product" + +#: core/models.py:534 msgid "the price paid to the vendor for this product" msgstr "De prijs die voor dit product aan de verkoper is betaald" -#: core/models.py:625 +#: core/models.py:535 msgid "vendor purchase price" msgstr "Aankoopprijs verkoper" -#: core/models.py:629 +#: core/models.py:539 msgid "available quantity of the product in stock" msgstr "Beschikbare hoeveelheid van het product in voorraad" -#: core/models.py:630 +#: core/models.py:540 msgid "quantity in stock" msgstr "Hoeveelheid op voorraad" -#: core/models.py:634 +#: core/models.py:544 msgid "vendor-assigned SKU for identifying the product" msgstr "Door de verkoper toegewezen SKU om het product te identificeren" -#: core/models.py:635 +#: core/models.py:545 msgid "vendor sku" msgstr "Verkoper SKU" -#: core/models.py:641 +#: core/models.py:551 msgid "digital file associated with this stock if applicable" msgstr "Digitaal bestand gekoppeld aan deze voorraad indien van toepassing" -#: core/models.py:642 +#: core/models.py:552 msgid "digital file" msgstr "Digitaal bestand" -#: core/models.py:651 +#: core/models.py:561 msgid "stock entries" msgstr "Voorraadboekingen" -#: core/models.py:660 +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "Categorie waartoe dit product behoort" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "Dit product optioneel koppelen aan een merk" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "Tags die dit product helpen beschrijven of groeperen" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "Geeft aan of dit product digitaal wordt geleverd" + +#: core/models.py:626 +msgid "is product digital" +msgstr "Is product digitaal" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "Zorg voor een duidelijke identificerende naam voor het product" + +#: core/models.py:633 +msgid "product name" +msgstr "Naam product" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "Voeg een gedetailleerde beschrijving van het product toe" + +#: core/models.py:639 +msgid "product description" +msgstr "Productbeschrijving" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "Onderdeelnummer voor dit product" + +#: core/models.py:647 +msgid "part number" +msgstr "Onderdeelnummer" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "Categorie van dit kenmerk" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "Groep van dit kenmerk" + +#: core/models.py:767 +msgid "string" +msgstr "String" + +#: core/models.py:768 +msgid "integer" +msgstr "Integer" + +#: core/models.py:769 +msgid "float" +msgstr "Vlotter" + +#: core/models.py:770 +msgid "boolean" +msgstr "Booleaans" + +#: core/models.py:771 +msgid "array" +msgstr "Array" + +#: core/models.py:772 +msgid "object" +msgstr "Object" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "Type waarde van het kenmerk" + +#: core/models.py:775 +msgid "value type" +msgstr "Waardetype" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "Naam van dit kenmerk" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "Naam attribuut" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "Attribuut" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "Attribuut van deze waarde" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "Het specifieke product geassocieerd met de waarde van dit kenmerk" + +#: core/models.py:837 +msgid "the specific value for this attribute" +msgstr "De specifieke waarde voor dit kenmerk" + +#: core/models.py:871 +msgid "provide alternative text for the image for accessibility" +msgstr "Geef alternatieve tekst voor de afbeelding voor toegankelijkheid" + +#: core/models.py:872 +msgid "image alt text" +msgstr "Alt-tekst afbeelding" + +#: core/models.py:875 +msgid "upload the image file for this product" +msgstr "Upload het afbeeldingsbestand voor dit product" + +#: core/models.py:876 core/models.py:901 +msgid "product image" +msgstr "Product afbeelding" + +#: core/models.py:882 +msgid "determines the order in which images are displayed" +msgstr "Bepaalt de volgorde waarin afbeeldingen worden weergegeven" + +#: core/models.py:883 +msgid "display priority" +msgstr "Prioriteit weergeven" + +#: core/models.py:888 +msgid "the product that this image represents" +msgstr "Het product dat deze afbeelding vertegenwoordigt" + +#: core/models.py:902 +msgid "product images" +msgstr "Product afbeeldingen" + +#: core/models.py:943 +msgid "percentage discount for the selected products" +msgstr "Kortingspercentage voor de geselecteerde producten" + +#: core/models.py:944 +msgid "discount percentage" +msgstr "Kortingspercentage" + +#: core/models.py:949 +msgid "provide a unique name for this promotion" +msgstr "Geef deze promotie een unieke naam" + +#: core/models.py:950 +msgid "promotion name" +msgstr "Naam promotie" + +#: core/models.py:956 +msgid "promotion description" +msgstr "Promotie beschrijving" + +#: core/models.py:961 +msgid "select which products are included in this promotion" +msgstr "Selecteer welke producten onder deze promotie vallen" + +#: core/models.py:962 +msgid "included products" +msgstr "Meegeleverde producten" + +#: core/models.py:966 +msgid "promotion" +msgstr "Promotie" + +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "Producten die de gebruiker als gewenst heeft gemarkeerd" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "Gebruiker die eigenaar is van deze verlanglijst" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "Eigenaar verlanglijstje" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "Verlanglijst" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} bestaat niet: {product_uuid}" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "Documentaire" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "Documentaires" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "Onopgelost" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "Adresregel voor de klant" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "Adresregel" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "Straat" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "District" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "Stad" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "Regio" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "Postcode" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "Land" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "Geolocatie Punt (lengtegraad, breedtegraad)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "Volledig JSON-antwoord van geocoder voor dit adres" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "Opgeslagen JSON-antwoord van de geocoderingsservice" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "Adres" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "Adressen" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "Unieke code die een gebruiker gebruikt om een korting te verzilveren" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "Promo code identificatie" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "" "Vast kortingsbedrag dat wordt toegepast als percentage niet wordt gebruikt" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "Vast kortingsbedrag" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "" "Kortingspercentage dat wordt toegepast als het vaste bedrag niet wordt " "gebruikt" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "Kortingspercentage" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "Tijdstempel wanneer de promocode verloopt" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "Geldigheidsduur einde" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "Tijdstempel vanaf wanneer deze promocode geldig is" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "Begin geldigheidsduur" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "" -"Tijdstempel wanneer de promocode werd gebruikt, leeg indien nog niet " -"gebruikt" +"Tijdstempel wanneer de promocode werd gebruikt, leeg indien nog niet gebruikt" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "Gebruik tijdstempel" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "Gebruiker toegewezen aan deze promocode indien van toepassing" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "Toegewezen gebruiker" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "Kortingscode" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "Actiecodes" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." msgstr "" -"Er moet slechts één type korting worden gedefinieerd (bedrag of percentage)," -" maar niet beide of geen van beide." +"Er moet slechts één type korting worden gedefinieerd (bedrag of percentage), " +"maar niet beide of geen van beide." -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "Promocode is al gebruikt" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "Ongeldig kortingstype voor promocode {self.uuid}" +msgstr "Ongeldig kortingstype voor promocode {self.uuid}!" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "Het factuuradres dat voor deze bestelling is gebruikt" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "Optionele promotiecode toegepast op deze bestelling" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "Kortingscode toegepast" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "Het verzendadres dat voor deze bestelling is gebruikt" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "Verzendadres" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "Huidige status van de order in zijn levenscyclus" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "Bestelstatus" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" "JSON-structuur van meldingen om weer te geven aan gebruikers, in admin UI " "wordt de tabelweergave gebruikt" -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "JSON-weergave van bestelattributen voor deze bestelling" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "De gebruiker die de bestelling heeft geplaatst" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "Gebruiker" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "De tijdstempel waarop de bestelling is afgerond" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "Tijd kopen" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "Een menselijk leesbare identificatiecode voor de bestelling" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "menselijk leesbare ID" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "Bestel" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "Een gebruiker mag maar één lopende order tegelijk hebben!" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "" "U kunt geen producten toevoegen aan een bestelling die niet in behandeling " "is." -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "U kunt geen inactieve producten toevoegen aan uw bestelling" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "Je kunt niet meer producten toevoegen dan er op voorraad zijn" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "" -"U kunt geen producten verwijderen uit een bestelling die niet in behandeling" -" is." +"U kunt geen producten verwijderen uit een bestelling die niet in behandeling " +"is." -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "{name} bestaat niet met query <{query}>" +msgstr "{name} bestaat niet met query <{query}>!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "Promocode bestaat niet" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "Je kunt alleen fysieke producten kopen met opgegeven verzendadres!" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "Adres bestaat niet" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "" "U kunt op dit moment niet kopen. Probeer het over een paar minuten nog eens." -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "Ongeldige krachtwaarde" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "Je kunt geen lege bestelling kopen!" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "" +"U kunt geen producten verwijderen uit een bestelling die niet in behandeling " +"is." + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "Een gebruiker zonder saldo kan niet kopen met saldo!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "Onvoldoende fondsen om de bestelling te voltooien" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" @@ -1983,122 +2018,124 @@ msgstr "" "u niet kunt kopen zonder registratie, geef dan de volgende informatie: " "klantnaam, e-mail klant, telefoonnummer klant" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" msgstr "" -"Ongeldige betalingsmethode: {payment_method} van " -"{available_payment_methods}!" +"Ongeldige betalingsmethode: {payment_method} van {available_payment_methods}!" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "De prijs die de klant bij aankoop voor dit product heeft betaald" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "Aankoopprijs bij bestelling" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "Interne opmerkingen voor beheerders over dit bestelde product" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "Interne opmerkingen" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "Meldingen van gebruikers" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "JSON weergave van de attributen van dit item" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "Geordende producteigenschappen" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "Verwijzing naar de bovenliggende bestelling die dit product bevat" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "Ouderlijk bevel" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "Het specifieke product dat bij deze bestelregel hoort" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "Hoeveelheid van dit specifieke product in de bestelling" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "Hoeveelheid product" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "Huidige status van dit product in de bestelling" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "Status productlijn" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "Orderproduct moet een bijbehorende order hebben!" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "verkeerde actie opgegeven voor feedback: {action}" +msgstr "Verkeerde actie opgegeven voor feedback: {action}!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "" -"U kunt geen producten verwijderen uit een bestelling die niet in behandeling" -" is." +"U kunt geen producten verwijderen uit een bestelling die niet in behandeling " +"is." -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "Downloaden" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "Downloads" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "" "U kunt geen digitale activa downloaden voor een niet-afgeronde bestelling" -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "Opmerkingen van gebruikers over hun ervaring met het product" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "Reacties" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "" "Verwijst naar het specifieke product in een bestelling waar deze feedback " "over gaat" -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "Gerelateerd product bestellen" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "Door de gebruiker toegekende waardering voor het product" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "Productbeoordeling" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "Feedback" @@ -2109,13 +2146,13 @@ msgstr "" "Om feedback toe te voegen, moet je een opmerking, beoordeling en " "productidentificatie opgeven." -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "Fout tijdens aanmaken promocode: {e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2124,7 +2161,7 @@ msgid "order confirmation" msgstr "Orderbevestiging" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2141,7 +2178,8 @@ msgstr "Hallo %(order.user.first_name)s," #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" msgstr "" "Hartelijk dank voor uw bestelling #%(order.pk)s! We zijn blij om u te " @@ -2149,14 +2187,14 @@ msgstr "" "vindt u de gegevens van uw bestelling:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "Totaal" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2176,23 +2214,23 @@ msgstr "" #: core/templates/digital_order_created_email.html:133 #, python-format msgid "best regards,
the %(config.PROJECT_NAME)s team" -msgstr "Vriendelijke groeten,
het %(config.PROJECT_NAME)s-team" +msgstr "Vriendelijke groeten,
het %(config.PROJECT_NAME)s team" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "Alle rechten voorbehouden" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "Bestelling geleverd" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "Hallo %(user_first_name)s," -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" @@ -2201,7 +2239,7 @@ msgstr "" "We hebben uw bestelling succesvol verwerkt №%(order_uuid)s! Hieronder vindt " "u de details van uw bestelling:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2209,12 +2247,12 @@ msgstr "" "aanvullende\n" " informatie" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "Waarde" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -2223,10 +2261,10 @@ msgstr "" "Als je vragen hebt, kun je contact opnemen met onze klantenservice op " "%(contact_email)s." -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Vriendelijke groeten,
het %(project_name)s-team" +msgstr "Vriendelijke groeten,
het %(project_name)s team" #: core/templates/json_table_widget.html:5 msgid "key" @@ -2235,7 +2273,8 @@ msgstr "Sleutel" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" msgstr "" "Bedankt voor uw bestelling! We zijn blij om uw aankoop te bevestigen. " @@ -2255,7 +2294,7 @@ msgstr "Je bestelling wordt afgeleverd op het volgende adres:" #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "Vriendelijke groeten,
het %(config.PROJECT_NAME)s-team" +msgstr "Vriendelijke groeten,
Het %(config.PROJECT_NAME)s team" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2272,33 +2311,22 @@ msgstr "Zowel gegevens als time-out zijn vereist" #: core/utils/caching.py:43 msgid "invalid timeout value, it must be between 0 and 216000 seconds" -msgstr "" -"Ongeldige time-outwaarde, deze moet tussen 0 en 216000 seconden liggen" - -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model} moet model zijn" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data} moet een lijstobject zijn" +msgstr "Ongeldige time-outwaarde, deze moet tussen 0 en 216000 seconden liggen" #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | Neem contact met ons op" +msgstr "{config.PROJECT_NAME} | neem contact met ons op" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" -msgstr "{config.PROJECT_NAME}. | Orderbevestiging" +msgstr "{config.PROJECT_NAME} | Orderbevestiging" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" -msgstr "{config.PROJECT_NAME}. | Geleverd" +msgstr "{config.PROJECT_NAME} | Bestelling afgeleverd" #: core/utils/messages.py:3 msgid "you do not have permission to perform this action." @@ -2319,15 +2347,15 @@ msgstr "" msgid "invalid phone number format" msgstr "Ongeldig formaat telefoonnummer" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "U kunt het digitale goed maar één keer downloaden" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "favicon niet gevonden" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "Fout bij geocodering: {e}" diff --git a/core/locale/pl_PL/LC_MESSAGES/django.mo b/core/locale/pl_PL/LC_MESSAGES/django.mo index 50475887..393bde22 100644 Binary files a/core/locale/pl_PL/LC_MESSAGES/django.mo and b/core/locale/pl_PL/LC_MESSAGES/django.mo differ diff --git a/core/locale/pl_PL/LC_MESSAGES/django.po b/core/locale/pl_PL/LC_MESSAGES/django.po index 98d57a93..ddfaf4d2 100644 --- a/core/locale/pl_PL/LC_MESSAGES/django.po +++ b/core/locale/pl_PL/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,122 +13,119 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "Unikalny identyfikator" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "" "Unikalny identyfikator służy do jednoznacznej identyfikacji dowolnego " "obiektu bazy danych" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "Jest aktywny" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" +"if set to false, this object can't be seen by users without needed permission" msgstr "" "Jeśli ustawione na false, obiekt ten nie może być widoczny dla użytkowników " "bez wymaganych uprawnień." -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "Utworzony" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "Kiedy obiekt po raz pierwszy pojawił się w bazie danych" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "Zmodyfikowany" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "Kiedy obiekt był ostatnio edytowany" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "Tłumaczenia" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "Ogólne" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "Relacje" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "Metadane" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "Znaczniki czasu" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" msgstr "Aktywuj wybrane %(verbose_name_plural)s" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)s aktywowany pomyślnie!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "Wybrane elementy zostały aktywowane!" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" -msgstr "Dezaktywacja wybranych %(verbose_name_plural)s" +msgstr "Dezaktywacja wybranego %(verbose_name_plural)s" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "Funkcja %(verbose_name_plural)s została pomyślnie dezaktywowana." +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "Wybrane elementy zostały dezaktywowane!" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "Wartość atrybutu" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "Wartości atrybutów" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "Obraz" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "Obrazy" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "Stan magazynowy" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "Akcje" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "Zamów produkt" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "Zamawianie produktów" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "Dzieci" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "Konfiguracja" @@ -180,7 +177,7 @@ msgstr "Momental" msgid "successful" msgstr "Udany" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "Pamięć podręczna we/wy" @@ -190,7 +187,8 @@ msgid "" "apply key, data and timeout with authentication to write data to cache." msgstr "" "Zastosuj tylko klucz, aby odczytać dozwolone dane z pamięci podręcznej.\n" -"Zastosuj klucz, dane i limit czasu z uwierzytelnianiem, aby zapisać dane w pamięci podręcznej." +"Zastosuj klucz, dane i limit czasu z uwierzytelnianiem, aby zapisać dane w " +"pamięci podręcznej." #: core/docs/drf/views.py:32 msgid "get a list of supported languages" @@ -204,7 +202,7 @@ msgstr "Uzyskaj dostępne parametry aplikacji" msgid "send a message to the support team" msgstr "Wyślij wiadomość do zespołu wsparcia" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "Żądanie adresu URL CORSed. Dozwolony jest tylko protokół https." @@ -247,8 +245,7 @@ msgstr "" "nieedytowalnych" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" +msgid "rewrite some fields of an existing attribute group saving non-editables" msgstr "" "Przepisanie niektórych pól istniejącej grupy atrybutów z zachowaniem " "atrybutów nieedytowalnych" @@ -303,8 +300,7 @@ msgstr "" "nieedytowalnych" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" +msgid "rewrite some fields of an existing attribute value saving non-editables" msgstr "" "Przepisz niektóre pola istniejącej wartości atrybutu, zapisując wartości " "nieedytowalne" @@ -347,11 +343,11 @@ msgstr "" #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" -"Wyszukiwanie podciągów z uwzględnieniem wielkości liter w human_readable_id," -" order_products.product.name i order_products.product.partnumber." +"Wyszukiwanie podciągów z uwzględnieniem wielkości liter w human_readable_id, " +"order_products.product.name i order_products.product.partnumber." #: core/docs/drf/viewsets.py:165 msgid "Filter orders with buy_time >= this ISO 8601 datetime" @@ -384,14 +380,14 @@ msgstr "Filtrowanie według identyfikatora UUID użytkownika" #: core/docs/drf/viewsets.py:195 msgid "Filter by order status (case-insensitive substring match)" msgstr "" -"Filtrowanie według statusu zamówienia (dopasowanie podciągu z uwzględnieniem" -" wielkości liter)" +"Filtrowanie według statusu zamówienia (dopasowanie podciągu z uwzględnieniem " +"wielkości liter)" #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" "Kolejność według jednego z: uuid, human_readable_id, user_email, user, " "status, created, modified, buy_time, random. Prefiks z \"-\" dla malejącego " @@ -437,7 +433,7 @@ msgstr "" "finalizowany przy użyciu salda użytkownika; Jeśli użyto `force_payment`, " "transakcja jest inicjowana." -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "zakup zamówienia bez tworzenia konta" @@ -571,18 +567,28 @@ msgstr "" msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "Filtrowanie według jednej lub więcej par atrybut/wartość. \n" "- Składnia**: `attr_name=method-value[;attr2=method2-value2]...`\n" -"- **Metody** (domyślnie `icontains` jeśli pominięte): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`\n" -"- Wpisywanie wartości**: JSON jest próbowany jako pierwszy (więc można przekazywać listy/dykty), `true`/`false` dla booleans, integers, floats; w przeciwnym razie traktowane jako string. \n" -"- Base64**: prefiks z `b64-` do bezpiecznego dla adresów URL kodowania base64 surowej wartości. \n" +"- **Metody** (domyślnie `icontains` jeśli pominięte): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`\n" +"- Wpisywanie wartości**: JSON jest próbowany jako pierwszy (więc można " +"przekazywać listy/dykty), `true`/`false` dla booleans, integers, floats; w " +"przeciwnym razie traktowane jako string. \n" +"- Base64**: prefiks z `b64-` do bezpiecznego dla adresów URL kodowania " +"base64 surowej wartości. \n" "Przykłady: \n" "`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\", \"bluetooth\"]`,\n" "`b64-description=icontains-aGVhdC1jb2xk`" @@ -637,10 +643,12 @@ msgstr "(dokładnie) Cyfrowe vs. fizyczne" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" -"Rozdzielana przecinkami lista pól do posortowania. Prefiks z `-` dla sortowania malejącego. \n" +"Rozdzielana przecinkami lista pól do posortowania. Prefiks z `-` dla " +"sortowania malejącego. \n" "**Dozwolone:** uuid, rating, name, slug, created, modified, price, random" #: core/docs/drf/viewsets.py:441 @@ -770,7 +778,7 @@ msgstr "usunąć relację zamówienie-produkt" msgid "add or remove feedback on an order–product relation" msgstr "dodawanie lub usuwanie opinii na temat relacji zamówienie-produkt" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "Nie podano wyszukiwanego hasła." @@ -818,8 +826,8 @@ msgstr "Atrybuty" msgid "Quantity" msgstr "Ilość" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "Ślimak" @@ -880,216 +888,239 @@ msgstr "Poziom" msgid "Product UUID" msgstr "UUID produktu" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "Klucz do wyszukania lub ustawienia w pamięci podręcznej" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "Dane do przechowywania w pamięci podręcznej" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "Limit czasu w sekundach na wprowadzenie danych do pamięci podręcznej" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "Dane w pamięci podręcznej" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "Kamelizowane dane JSON z żądanego adresu URL" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "Dozwolone są tylko adresy URL zaczynające się od http(s)://" -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "Dodawanie produktu do zamówienia" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "Nie znaleziono zamówienia {order_uuid}" +msgstr "Nie znaleziono zamówienia {order_uuid}!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "Usunięcie produktu z zamówienia" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "Usuń wszystkie produkty z zamówienia" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "Kup zamówienie" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "Podaj albo order_uuid albo order_hr_id - wzajemnie się wykluczają!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "Nieprawidłowy typ pochodzi z metody order.buy(): {type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "Wykonanie akcji na liście produktów w zamówieniu" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "Usuń/Dodaj" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "Akcją musi być \"dodaj\" lub \"usuń\"!" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "Wykonanie akcji na liście produktów na liście życzeń" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "Podaj wartość `wishlist_uuid`." + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "Lista życzeń {wishlist_uuid} nie została znaleziona!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "Dodawanie produktu do zamówienia" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "Lista życzeń {wishlist_uuid} nie została znaleziona" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "Usunięcie produktu z zamówienia" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "Usunięcie produktu z zamówienia" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "Usunięcie produktu z zamówienia" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "Kup zamówienie" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" msgstr "" "Prześlij atrybuty jako ciąg znaków sformatowany w następujący sposób: " "attr1=value1,attr2=value2" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "Dodawanie lub usuwanie opinii dla produktu zamówienia" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "Akcją musi być `add` lub `remove`!" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "Orderproduct {order_product_uuid} nie został znaleziony!" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "Oryginalny ciąg adresu podany przez użytkownika" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} nie istnieje: {uuid}" +msgstr "{name} nie istnieje: {uuid}!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "Limit musi wynosić od 1 do 10" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - działa jak urok" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "Atrybuty" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "Atrybuty pogrupowane" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "Grupy atrybutów" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "Kategorie" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "Marki" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "Kategorie" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "Procentowy narzut" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "" "Które atrybuty i wartości mogą być używane do filtrowania tej kategorii." -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." +#: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." msgstr "" "Minimalne i maksymalne ceny produktów w tej kategorii, jeśli są dostępne." -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "Tagi dla tej kategorii" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "Produkty w tej kategorii" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "Sprzedawcy" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "Szerokość geograficzna (współrzędna Y)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "Długość geograficzna (współrzędna X)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "Jak" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "Wartość oceny od 1 do 10 włącznie lub 0, jeśli nie jest ustawiona." -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "Reprezentuje informacje zwrotne od użytkownika." -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "Powiadomienia" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "Adres URL pobierania dla tego produktu zamówienia, jeśli dotyczy" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "Lista zamówionych produktów w tym zamówieniu" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "Adres rozliczeniowy" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" @@ -1097,733 +1128,730 @@ msgstr "" "Adres wysyłki dla tego zamówienia, pozostaw pusty, jeśli jest taki sam jak " "adres rozliczeniowy lub jeśli nie dotyczy" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "Całkowita cena tego zamówienia" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "Całkowita ilość produktów w zamówieniu" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "Czy wszystkie produkty w zamówieniu są cyfrowe?" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "Transakcje dla tego zamówienia" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "Zamówienia" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "Adres URL obrazu" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "Zdjęcia produktu" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "Kategoria" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "Informacje zwrotne" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "Marka" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "Grupy atrybutów" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "Cena" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "Ilość" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "Liczba informacji zwrotnych" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "Produkty" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "Promocodes" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "Produkty w sprzedaży" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "Promocje" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "Sprzedawca" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "Produkt" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "Produkty z listy życzeń" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "Listy życzeń" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "Produkty Tagged" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "Tagi produktu" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "Kategorie oznaczone tagami" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "Tagi kategorii" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "Nazwa projektu" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "Firmowy adres e-mail" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "Nazwa firmy" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "Adres firmy" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "Numer telefonu firmy" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" -msgstr "\"email from\", czasami musi być użyty zamiast wartości użytkownika hosta" +msgstr "" +"\"email from\", czasami musi być użyty zamiast wartości użytkownika hosta" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "Użytkownik hosta poczty e-mail" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "Maksymalna kwota płatności" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "Minimalna kwota płatności" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "Dane analityczne" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "Dane reklamowe" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "Konfiguracja" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "Kod języka" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "Nazwa języka" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "Flaga języka, jeśli istnieje :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "Pobierz listę obsługiwanych języków" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "Wyniki wyszukiwania produktów" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "Wyniki wyszukiwania produktów" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "Rodzic tej grupy" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "Grupa atrybutów nadrzędnych" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "Nazwa grupy atrybutów" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "Grupa atrybutów" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" "Przechowuje dane uwierzytelniające i punkty końcowe wymagane do komunikacji " "API dostawcy." -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "Informacje o uwierzytelnianiu" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "Definiowanie znaczników dla produktów pobranych od tego dostawcy" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "Procentowa marża sprzedawcy" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "Nazwa tego sprzedawcy" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "Nazwa sprzedawcy" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "Wewnętrzny identyfikator tagu produktu" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "Nazwa tagu" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "Przyjazna dla użytkownika nazwa etykiety produktu" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "Wyświetlana nazwa znacznika" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "Etykieta produktu" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "tag kategorii" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "tagi kategorii" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "Prześlij obraz reprezentujący tę kategorię" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "Obraz kategorii" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "Zdefiniuj procentowy narzut dla produktów w tej kategorii." -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "Rodzic tej kategorii w celu utworzenia struktury hierarchicznej" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "Kategoria nadrzędna" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "Nazwa kategorii" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "Podaj nazwę dla tej kategorii" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "Dodaj szczegółowy opis dla tej kategorii" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "Opis kategorii" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "tagi, które pomagają opisać lub pogrupować tę kategorię" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "Priorytet" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "Nazwa tej marki" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "Nazwa marki" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "Prześlij logo reprezentujące tę markę" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "Mały wizerunek marki" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "Prześlij duże logo reprezentujące tę markę" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "Duży wizerunek marki" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "Dodaj szczegółowy opis marki" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "Opis marki" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "Opcjonalne kategorie, z którymi powiązana jest ta marka" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "Kategorie" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "Kategoria, do której należy ten produkt" - -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "Opcjonalnie można powiązać ten produkt z marką" - -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "Tagi, które pomagają opisać lub pogrupować ten produkt" - -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "Wskazuje, czy produkt jest dostarczany cyfrowo." - -#: core/models.py:351 -msgid "is product digital" -msgstr "Czy produkt jest cyfrowy?" - -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "Wyraźna nazwa identyfikująca produkt" - -#: core/models.py:358 -msgid "product name" -msgstr "Nazwa produktu" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "Dodaj szczegółowy opis produktu" - -#: core/models.py:364 -msgid "product description" -msgstr "Opis produktu" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "Numer części dla tego produktu" - -#: core/models.py:372 -msgid "part number" -msgstr "Numer części" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "Kategoria tego atrybutu" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "Grupa tego atrybutu" - -#: core/models.py:465 -msgid "string" -msgstr "String" - -#: core/models.py:466 -msgid "integer" -msgstr "Integer" - -#: core/models.py:467 -msgid "float" -msgstr "Pływak" - -#: core/models.py:468 -msgid "boolean" -msgstr "Wartość logiczna" - -#: core/models.py:469 -msgid "array" -msgstr "Tablica" - -#: core/models.py:470 -msgid "object" -msgstr "Obiekt" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "Typ wartości atrybutu" - -#: core/models.py:473 -msgid "value type" -msgstr "Typ wartości" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "Nazwa tego atrybutu" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "Nazwa atrybutu" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "Atrybut" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "Atrybut tej wartości" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "Konkretny produkt powiązany z wartością tego atrybutu" - -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 -msgid "associated product" -msgstr "Produkt powiązany" - -#: core/models.py:512 -msgid "the specific value for this attribute" -msgstr "Konkretna wartość dla tego atrybutu" - -#: core/models.py:528 -msgid "provide alternative text for the image for accessibility" -msgstr "" -"Zapewnienie alternatywnego tekstu dla obrazu w celu ułatwienia dostępu" - -#: core/models.py:529 -msgid "image alt text" -msgstr "Tekst alternatywny obrazu" - -#: core/models.py:532 -msgid "upload the image file for this product" -msgstr "Prześlij plik obrazu dla tego produktu" - -#: core/models.py:533 core/models.py:558 -msgid "product image" -msgstr "Obraz produktu" - -#: core/models.py:539 -msgid "determines the order in which images are displayed" -msgstr "Określa kolejność wyświetlania obrazów" - -#: core/models.py:540 -msgid "display priority" -msgstr "Priorytet wyświetlania" - -#: core/models.py:545 -msgid "the product that this image represents" -msgstr "Produkt, który przedstawia ten obraz" - -#: core/models.py:559 -msgid "product images" -msgstr "Zdjęcia produktów" - -#: core/models.py:567 -msgid "percentage discount for the selected products" -msgstr "Rabat procentowy na wybrane produkty" - -#: core/models.py:568 -msgid "discount percentage" -msgstr "Procent rabatu" - -#: core/models.py:573 -msgid "provide a unique name for this promotion" -msgstr "Podaj unikalną nazwę tej promocji" - -#: core/models.py:574 -msgid "promotion name" -msgstr "Nazwa promocji" - -#: core/models.py:580 -msgid "promotion description" -msgstr "Opis promocji" - -#: core/models.py:585 -msgid "select which products are included in this promotion" -msgstr "Wybierz produkty objęte promocją" - -#: core/models.py:586 -msgid "included products" -msgstr "Dołączone produkty" - -#: core/models.py:590 -msgid "promotion" -msgstr "Promocja" - -#: core/models.py:605 +#: core/models.py:515 msgid "the vendor supplying this product stock" msgstr "Sprzedawca dostarczający ten produkt" -#: core/models.py:606 +#: core/models.py:516 msgid "associated vendor" msgstr "Powiązany sprzedawca" -#: core/models.py:610 +#: core/models.py:520 msgid "final price to the customer after markups" msgstr "Ostateczna cena dla klienta po uwzględnieniu marży" -#: core/models.py:611 +#: core/models.py:521 msgid "selling price" msgstr "Cena sprzedaży" -#: core/models.py:616 +#: core/models.py:526 msgid "the product associated with this stock entry" msgstr "Produkt powiązany z tym wpisem magazynowym" -#: core/models.py:624 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "Produkt powiązany" + +#: core/models.py:534 msgid "the price paid to the vendor for this product" msgstr "Cena zapłacona sprzedawcy za ten produkt" -#: core/models.py:625 +#: core/models.py:535 msgid "vendor purchase price" msgstr "Cena zakupu przez sprzedawcę" -#: core/models.py:629 +#: core/models.py:539 msgid "available quantity of the product in stock" msgstr "Dostępna ilość produktu w magazynie" -#: core/models.py:630 +#: core/models.py:540 msgid "quantity in stock" msgstr "Ilość w magazynie" -#: core/models.py:634 +#: core/models.py:544 msgid "vendor-assigned SKU for identifying the product" msgstr "Jednostki SKU przypisane przez dostawcę w celu identyfikacji produktu" -#: core/models.py:635 +#: core/models.py:545 msgid "vendor sku" msgstr "SKU sprzedawcy" -#: core/models.py:641 +#: core/models.py:551 msgid "digital file associated with this stock if applicable" msgstr "Plik cyfrowy powiązany z tymi zapasami, jeśli dotyczy" -#: core/models.py:642 +#: core/models.py:552 msgid "digital file" msgstr "Plik cyfrowy" -#: core/models.py:651 +#: core/models.py:561 msgid "stock entries" msgstr "Zapisy magazynowe" -#: core/models.py:660 +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "Kategoria, do której należy ten produkt" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "Opcjonalnie można powiązać ten produkt z marką" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "Tagi, które pomagają opisać lub pogrupować ten produkt" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "Wskazuje, czy produkt jest dostarczany cyfrowo." + +#: core/models.py:626 +msgid "is product digital" +msgstr "Czy produkt jest cyfrowy?" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "Wyraźna nazwa identyfikująca produkt" + +#: core/models.py:633 +msgid "product name" +msgstr "Nazwa produktu" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "Dodaj szczegółowy opis produktu" + +#: core/models.py:639 +msgid "product description" +msgstr "Opis produktu" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "Numer części dla tego produktu" + +#: core/models.py:647 +msgid "part number" +msgstr "Numer części" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "Kategoria tego atrybutu" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "Grupa tego atrybutu" + +#: core/models.py:767 +msgid "string" +msgstr "String" + +#: core/models.py:768 +msgid "integer" +msgstr "Integer" + +#: core/models.py:769 +msgid "float" +msgstr "Pływak" + +#: core/models.py:770 +msgid "boolean" +msgstr "Wartość logiczna" + +#: core/models.py:771 +msgid "array" +msgstr "Tablica" + +#: core/models.py:772 +msgid "object" +msgstr "Obiekt" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "Typ wartości atrybutu" + +#: core/models.py:775 +msgid "value type" +msgstr "Typ wartości" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "Nazwa tego atrybutu" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "Nazwa atrybutu" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "Atrybut" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "Atrybut tej wartości" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "Konkretny produkt powiązany z wartością tego atrybutu" + +#: core/models.py:837 +msgid "the specific value for this attribute" +msgstr "Konkretna wartość dla tego atrybutu" + +#: core/models.py:871 +msgid "provide alternative text for the image for accessibility" +msgstr "Zapewnienie alternatywnego tekstu dla obrazu w celu ułatwienia dostępu" + +#: core/models.py:872 +msgid "image alt text" +msgstr "Tekst alternatywny obrazu" + +#: core/models.py:875 +msgid "upload the image file for this product" +msgstr "Prześlij plik obrazu dla tego produktu" + +#: core/models.py:876 core/models.py:901 +msgid "product image" +msgstr "Obraz produktu" + +#: core/models.py:882 +msgid "determines the order in which images are displayed" +msgstr "Określa kolejność wyświetlania obrazów" + +#: core/models.py:883 +msgid "display priority" +msgstr "Priorytet wyświetlania" + +#: core/models.py:888 +msgid "the product that this image represents" +msgstr "Produkt, który przedstawia ten obraz" + +#: core/models.py:902 +msgid "product images" +msgstr "Zdjęcia produktów" + +#: core/models.py:943 +msgid "percentage discount for the selected products" +msgstr "Rabat procentowy na wybrane produkty" + +#: core/models.py:944 +msgid "discount percentage" +msgstr "Procent rabatu" + +#: core/models.py:949 +msgid "provide a unique name for this promotion" +msgstr "Podaj unikalną nazwę tej promocji" + +#: core/models.py:950 +msgid "promotion name" +msgstr "Nazwa promocji" + +#: core/models.py:956 +msgid "promotion description" +msgstr "Opis promocji" + +#: core/models.py:961 +msgid "select which products are included in this promotion" +msgstr "Wybierz produkty objęte promocją" + +#: core/models.py:962 +msgid "included products" +msgstr "Dołączone produkty" + +#: core/models.py:966 +msgid "promotion" +msgstr "Promocja" + +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "Produkty, które użytkownik oznaczył jako poszukiwane" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "Użytkownik posiadający tę listę życzeń" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "Właściciel listy życzeń" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "Lista życzeń" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} nie istnieje: {product_uuid}" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "Film dokumentalny" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "Filmy dokumentalne" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "Nierozwiązany" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "Linia adresu dla klienta" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "Linia adresowa" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "ul." -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "Okręg" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "Miasto" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "Region" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "Kod pocztowy" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "Kraj" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "Geolocation Point(Longitude, Latitude)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "Pełna odpowiedź JSON z geokodera dla tego adresu" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "Przechowywana odpowiedź JSON z usługi geokodowania" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "Adres" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "Adresy" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "Unikalny kod używany przez użytkownika do realizacji rabatu." -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "Identyfikator kodu promocyjnego" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "Stała kwota rabatu stosowana, jeśli procent nie jest używany" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "Stała kwota rabatu" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "Rabat procentowy stosowany w przypadku niewykorzystania stałej kwoty" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "Rabat procentowy" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "Znacznik czasu wygaśnięcia kodu promocyjnego" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "Końcowy czas ważności" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "Znacznik czasu, od którego ten kod promocyjny jest ważny" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "Czas rozpoczęcia ważności" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "" "Znacznik czasu użycia kodu promocyjnego, pusty, jeśli nie został jeszcze " "użyty." -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "Znacznik czasu użycia" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "Użytkownik przypisany do tego kodu promocyjnego, jeśli dotyczy" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "Przypisany użytkownik" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "Kod promocyjny" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "Kody promocyjne" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." @@ -1831,141 +1859,150 @@ msgstr "" "Należy zdefiniować tylko jeden rodzaj rabatu (kwotowy lub procentowy), ale " "nie oba lub żaden z nich." -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "Kod promocyjny został już wykorzystany" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "Nieprawidłowy typ rabatu dla kodu promocyjnego {self.uuid}." +msgstr "Nieprawidłowy typ rabatu dla kodu promocyjnego {self.uuid}!" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "Adres rozliczeniowy użyty dla tego zamówienia" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "Opcjonalny kod promocyjny zastosowany do tego zamówienia" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "Zastosowany kod promocyjny" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "Adres wysyłki użyty dla tego zamówienia" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "Adres wysyłki" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "Aktualny status zamówienia w jego cyklu życia" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "Status zamówienia" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" "Struktura JSON powiadomień do wyświetlenia użytkownikom, w interfejsie " "administratora używany jest widok tabeli" -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "Reprezentacja JSON atrybutów zamówienia dla tego zamówienia" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "Użytkownik, który złożył zamówienie" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "Użytkownik" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "Znacznik czasu, kiedy zamówienie zostało sfinalizowane" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "Kup czas" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "Czytelny dla człowieka identyfikator zamówienia" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "Identyfikator czytelny dla człowieka" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "Zamówienie" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" -msgstr "" -"Użytkownik może mieć tylko jedno oczekujące zlecenie w danym momencie!" +msgstr "Użytkownik może mieć tylko jedno oczekujące zlecenie w danym momencie!" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "" "Nie można dodać produktów do zamówienia, które nie jest zamówieniem " "oczekującym." -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "Nie można dodać nieaktywnych produktów do zamówienia" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "Nie można dodać więcej produktów niż jest dostępnych w magazynie" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "" "Nie można usunąć produktów z zamówienia, które nie jest zamówieniem " "oczekującym." -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "{name} nie istnieje z zapytaniem <{query}>." +msgstr "{name} nie istnieje z zapytaniem <{query}>!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "Kod promocyjny nie istnieje" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "Możesz kupować tylko produkty fizyczne z podanym adresem wysyłki!" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "Adres nie istnieje" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "" "W tej chwili nie możesz dokonać zakupu, spróbuj ponownie za kilka minut." -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "Nieprawidłowa wartość siły" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "Nie można kupić pustego zamówienia!" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "" +"Nie można usunąć produktów z zamówienia, które nie jest zamówieniem " +"oczekującym." + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "Użytkownik bez salda nie może kupować za saldo!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "Niewystarczające środki do zrealizowania zamówienia" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" @@ -1974,7 +2011,7 @@ msgstr "" "informacje: imię i nazwisko klienta, adres e-mail klienta, numer telefonu " "klienta." -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" @@ -1982,115 +2019,117 @@ msgstr "" "Nieprawidłowa metoda płatności: {payment_method} z " "{available_payment_methods}!" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "Cena zapłacona przez klienta za ten produkt w momencie zakupu." -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "Cena zakupu w momencie zamówienia" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "" -"Wewnętrzne komentarze dla administratorów dotyczące tego zamówionego " -"produktu" +"Wewnętrzne komentarze dla administratorów dotyczące tego zamówionego produktu" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "Uwagi wewnętrzne" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "Powiadomienia użytkownika" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "Reprezentacja JSON atrybutów tego elementu" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "Zamówione atrybuty produktu" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "Odniesienie do zamówienia nadrzędnego zawierającego ten produkt" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "Zamówienie nadrzędne" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "Konkretny produkt powiązany z tą linią zamówienia" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "Ilość tego konkretnego produktu w zamówieniu" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "Ilość produktu" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "Aktualny status tego produktu w zamówieniu" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "Status linii produktów" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "Orderproduct musi mieć powiązane zamówienie!" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "nieprawidłowe działanie określone dla informacji zwrotnej: {action}" +msgstr "Nieprawidłowa akcja określona dla informacji zwrotnej: {action}!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "" "Nie można usunąć produktów z zamówienia, które nie jest zamówieniem " "oczekującym." -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "Pobierz" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "Pliki do pobrania" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "Nie można pobrać zasobu cyfrowego dla nieukończonego zamówienia." -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "Komentarze użytkowników na temat ich doświadczeń z produktem" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "Komentarze zwrotne" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "" "Odnosi się do konkretnego produktu w zamówieniu, którego dotyczy ta " "informacja zwrotna." -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "Powiązany produkt zamówienia" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "Ocena produktu przypisana przez użytkownika" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "Ocena produktu" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "Informacje zwrotne" @@ -2101,13 +2140,13 @@ msgstr "" "Aby dodać opinię, należy podać komentarz, ocenę i identyfikator produktu " "zamówienia." -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "Błąd podczas tworzenia kodu promocyjnego: {e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2116,7 +2155,7 @@ msgid "order confirmation" msgstr "Potwierdzenie zamówienia" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2127,13 +2166,14 @@ msgstr "Logo" #: core/templates/shipped_order_delivered_email.html:100 #, python-format msgid "hello %(order.user.first_name)s," -msgstr "Witam %(order.user.first_name)s," +msgstr "Witaj %(order.user.first_name)s," #: core/templates/digital_order_created_email.html:102 #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" msgstr "" "Dziękujemy za zamówienie #%(order.pk)s! Z przyjemnością informujemy, że " @@ -2141,14 +2181,14 @@ msgstr "" "zamówienia:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "Łącznie" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2168,32 +2208,32 @@ msgstr "" #: core/templates/digital_order_created_email.html:133 #, python-format msgid "best regards,
the %(config.PROJECT_NAME)s team" -msgstr "Z wyrazami szacunku,
zespół %(config.PROJECT_NAME)s" +msgstr "Najlepsze pozdrowienia,
zespół %(config.PROJECT_NAME)s" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "Wszelkie prawa zastrzeżone" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "Zamówienie dostarczone" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "Witaj %(user_first_name)s," -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" " details of your order:" msgstr "" -"Pomyślnie przetworzyliśmy Twoje zamówienie №%(order_uuid)s! Poniżej znajdują" -" się szczegóły zamówienia:" +"Pomyślnie przetworzyliśmy Twoje zamówienie №%(order_uuid)s! Poniżej znajdują " +"się szczegóły zamówienia:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2201,12 +2241,12 @@ msgstr "" "dodatkowe\n" " informacje" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "Wartość" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -2215,10 +2255,10 @@ msgstr "" "Jeśli masz jakiekolwiek pytania, skontaktuj się z naszym działem pomocy " "technicznej pod adresem %(contact_email)s." -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Z wyrazami szacunku,
zespół %(project_name)s" +msgstr "Najlepsze pozdrowienia,
zespół %(project_name)s" #: core/templates/json_table_widget.html:5 msgid "key" @@ -2227,7 +2267,8 @@ msgstr "Klucz" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" msgstr "" "Dziękujemy za zamówienie! Z przyjemnością potwierdzamy zakup. Poniżej " @@ -2247,7 +2288,7 @@ msgstr "Zamówienie zostanie dostarczone pod następujący adres:" #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "Z wyrazami szacunku, zespół %(config.PROJECT_NAME)s" +msgstr "Z wyrazami szacunku,
Zespół %(config.PROJECT_NAME)s" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2268,27 +2309,17 @@ msgstr "" "Nieprawidłowa wartość limitu czasu, musi zawierać się w przedziale od 0 do " "216000 sekund." -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model} musi być modelem" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data} musi być obiektem listy" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | Kontakt zainicjowany" +msgstr "{config.PROJECT_NAME} | zainicjowany kontakt" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" msgstr "{config.PROJECT_NAME} | Potwierdzenie zamówienia" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" msgstr "{config.PROJECT_NAME} | Zamówienie dostarczone" @@ -2311,15 +2342,15 @@ msgstr "" msgid "invalid phone number format" msgstr "Nieprawidłowy format numeru telefonu" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "Zasób cyfrowy można pobrać tylko raz" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "nie znaleziono favicon" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "Błąd geokodowania: {e}" diff --git a/core/locale/pt_BR/LC_MESSAGES/django.mo b/core/locale/pt_BR/LC_MESSAGES/django.mo index a97749b1..5f2c14e5 100644 Binary files a/core/locale/pt_BR/LC_MESSAGES/django.mo and b/core/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/core/locale/pt_BR/LC_MESSAGES/django.po b/core/locale/pt_BR/LC_MESSAGES/django.po index 4aa66926..ed2db556 100644 --- a/core/locale/pt_BR/LC_MESSAGES/django.po +++ b/core/locale/pt_BR/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,122 +13,119 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "ID exclusivo" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "" "O ID exclusivo é usado para identificar com segurança qualquer objeto do " "banco de dados" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "Está ativo" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" +"if set to false, this object can't be seen by users without needed permission" msgstr "" "Se definido como false, esse objeto não poderá ser visto por usuários sem a " "permissão necessária" -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "Criado" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "Quando o objeto apareceu pela primeira vez no banco de dados" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "Modificado" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "Quando o objeto foi editado pela última vez" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "Traduções" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "Geral" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "Relações" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "Metadados" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "Carimbos de data/hora" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" -msgstr "Ativar %(verbose_name_plural)s selecionados" +msgstr "Ativar o %(verbose_name_plural)s selecionado" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)s ativado com sucesso!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "Os itens selecionados foram ativados!" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" -msgstr "Desativar %(verbose_name_plural)s selecionados" +msgstr "Desativar o %(verbose_name_plural)s selecionado" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "%(verbose_name_plural)s desativado com sucesso." +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "Os itens selecionados foram desativados!" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "Valor do atributo" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "Valores de atributos" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "Imagem" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "Imagens" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "Estoque" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "Ações" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "Pedido de produto" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "Solicitar produtos" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "Crianças" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "Configuração" @@ -180,7 +177,7 @@ msgstr "Momental" msgid "successful" msgstr "Bem-sucedido" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "E/S do cache" @@ -190,7 +187,8 @@ msgid "" "apply key, data and timeout with authentication to write data to cache." msgstr "" "Aplicar somente uma chave para ler dados permitidos do cache.\n" -"Aplicar chave, dados e tempo limite com autenticação para gravar dados no cache." +"Aplicar chave, dados e tempo limite com autenticação para gravar dados no " +"cache." #: core/docs/drf/views.py:32 msgid "get a list of supported languages" @@ -204,7 +202,7 @@ msgstr "Obter os parâmetros expostos do aplicativo" msgid "send a message to the support team" msgstr "Envie uma mensagem para a equipe de suporte" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "Solicite um URL com CORS. Somente https é permitido." @@ -246,8 +244,7 @@ msgid "rewrite an existing attribute group saving non-editables" msgstr "Reescrever um grupo de atributos existente salvando os não editáveis" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" +msgid "rewrite some fields of an existing attribute group saving non-editables" msgstr "" "Reescreva alguns campos de um grupo de atributos existente salvando os não " "editáveis" @@ -298,8 +295,7 @@ msgid "rewrite an existing attribute value saving non-editables" msgstr "Reescreva um valor de atributo existente salvando os não editáveis" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" +msgid "rewrite some fields of an existing attribute value saving non-editables" msgstr "" "Reescreva alguns campos de um valor de atributo existente salvando os não " "editáveis" @@ -340,12 +336,12 @@ msgstr "" #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" "Pesquisa de substring sem distinção entre maiúsculas e minúsculas em " -"human_readable_id, order_products.product.name e " -"order_products.product.partnumber" +"human_readable_id, order_products.product.name e order_products.product." +"partnumber" #: core/docs/drf/viewsets.py:165 msgid "Filter orders with buy_time >= this ISO 8601 datetime" @@ -381,9 +377,9 @@ msgstr "" #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" "Ordene por uma das seguintes opções: uuid, human_readable_id, user_email, " "user, status, created, modified, buy_time, random. Prefixe com '-' para " @@ -428,7 +424,7 @@ msgstr "" "concluída usando o saldo do usuário; se `force_payment` for usado, uma " "transação será iniciada." -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "comprar um pedido sem criar uma conta" @@ -564,18 +560,28 @@ msgstr "" msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "Filtrar por um ou mais pares de nome/valor de atributo. \n" "- **Sintaxe**: `attr_name=method-value[;attr2=method2-value2]...`\n" -"- Métodos** (o padrão é `icontains` se omitido): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`\n" -"- Digitação de valores**: JSON é tentado primeiro (para que você possa passar listas/dicas), `true`/`false` para booleanos, inteiros, flutuantes; caso contrário, é tratado como string. \n" -"- Base64**: prefixo com `b64-` para codificar o valor bruto com base64 de forma segura para a URL. \n" +"- Métodos** (o padrão é `icontains` se omitido): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`\n" +"- Digitação de valores**: JSON é tentado primeiro (para que você possa " +"passar listas/dicas), `true`/`false` para booleanos, inteiros, flutuantes; " +"caso contrário, é tratado como string. \n" +"- Base64**: prefixo com `b64-` para codificar o valor bruto com base64 de " +"forma segura para a URL. \n" "Exemplos: \n" "`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\", \"bluetooth\"]`,\n" "`b64-description=icontains-aGVhdC1jb2xk`" @@ -631,11 +637,14 @@ msgstr "(exato) Digital vs. físico" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" -"Lista de campos separada por vírgulas para classificação. Prefixe com `-` para classificação decrescente. \n" -"**Permitido:** uuid, classificação, nome, slug, criado, modificado, preço, aleatório" +"Lista de campos separada por vírgulas para classificação. Prefixe com `-` " +"para classificação decrescente. \n" +"**Permitido:** uuid, classificação, nome, slug, criado, modificado, preço, " +"aleatório" #: core/docs/drf/viewsets.py:441 msgid "retrieve a single product (detailed view)" @@ -761,7 +770,7 @@ msgstr "excluir uma relação pedido-produto" msgid "add or remove feedback on an order–product relation" msgstr "adicionar ou remover feedback em uma relação pedido-produto" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "Nenhum termo de pesquisa foi fornecido." @@ -809,8 +818,8 @@ msgstr "Atributos" msgid "Quantity" msgstr "Quantidade" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "Lesma" @@ -872,215 +881,238 @@ msgstr "Nível" msgid "Product UUID" msgstr "UUID do produto" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "Chave para procurar ou colocar no cache" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "Dados a serem armazenados no cache" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "Tempo limite em segundos para definir os dados para o cache" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "Dados em cache" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "Dados JSON camelizados da URL solicitada" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "Somente URLs que começam com http(s):// são permitidos" -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "Adicionar um produto ao pedido" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "Pedido {order_uuid} não encontrado" +msgstr "Pedido {order_uuid} não encontrado!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "Remover um produto do pedido" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "Remover todos os produtos do pedido" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "Comprar um pedido" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "Forneça order_uuid ou order_hr_id - mutuamente exclusivos!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "O tipo errado veio do método order.buy(): {type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "Executar uma ação em uma lista de produtos no pedido" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "Remover/Adicionar" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "A ação deve ser \"adicionar\" ou \"remover\"!" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "Executar uma ação em uma lista de produtos na lista de desejos" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "Forneça o valor `wishlist_uuid`." + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "Lista de desejos {wishlist_uuid} não encontrada!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "Adicionar um produto ao pedido" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "Lista de desejos {wishlist_uuid} não encontrada" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "Remover um produto do pedido" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "Remover um produto do pedido" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "Remover um produto do pedido" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "Comprar um pedido" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" msgstr "" "Envie os atributos como uma string formatada como attr1=value1,attr2=value2" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "Adicionar ou excluir um feedback para o produto do pedido" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "A ação deve ser `add` ou `remove`!" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "Orderproduct {order_product_uuid} não encontrado!" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "Cadeia de endereços original fornecida pelo usuário" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} não existe: {uuid}" +msgstr "{name} não existe: {uuid}!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "O limite deve estar entre 1 e 10" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - funciona muito bem" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "Atributos" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "Atributos agrupados" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "Grupos de atributos" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "Categorias" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "Marcas" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "Categorias" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "Porcentagem de marcação" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "" "Quais atributos e valores podem ser usados para filtrar essa categoria." -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." +#: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." msgstr "Preços mínimo e máximo dos produtos dessa categoria, se disponíveis." -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "Tags para esta categoria" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "Produtos desta categoria" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "Vendors" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "Latitude (coordenada Y)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "Longitude (coordenada X)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "Como fazer" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "" "Valor de classificação de 1 a 10, inclusive, ou 0 se não estiver definido." -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "Representa o feedback de um usuário." -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "Notificações" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "URL de download para este produto do pedido, se aplicável" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "Uma lista dos produtos solicitados nesse pedido" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "Endereço de cobrança" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" @@ -1088,875 +1120,878 @@ msgstr "" "Endereço de entrega para este pedido, deixe em branco se for o mesmo que o " "endereço de cobrança ou se não for aplicável" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "Preço total deste pedido" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "Quantidade total de produtos no pedido" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "Todos os produtos estão no pedido digital?" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "Transações para esta ordem" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "Pedidos" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "URL da imagem" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "Imagens do produto" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "Categoria" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "Feedbacks" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "Brand" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "Grupos de atributos" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "Preço" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "Quantidade" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "Número de feedbacks" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "Produtos" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "Códigos promocionais" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "Produtos à venda" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "Promoções" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "Vendor" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "Produto" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "Produtos da lista de desejos" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "Listas de desejos" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "Produtos marcados" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "Etiquetas do produto" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "Categorias de tags" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "Tags das categorias" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "Nome do projeto" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "E-mail da empresa" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "Nome da empresa" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "Endereço da empresa" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "Número de telefone da empresa" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "" "'email from', às vezes ele deve ser usado em vez do valor do usuário do host" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "Usuário do host de e-mail" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "Valor máximo para pagamento" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "Valor mínimo para pagamento" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "Dados analíticos" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "Dados do anúncio" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "Configuração" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "Código do idioma" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "Nome do idioma" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "Sinalizador de idioma, se houver :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "Obter uma lista de idiomas suportados" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "Resultados da pesquisa de produtos" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "Resultados da pesquisa de produtos" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "Pai deste grupo" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "Grupo de atributos pai" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "Nome do grupo de atributos" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "Grupo de atributos" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" "Armazena as credenciais e os pontos de extremidade necessários para a " "comunicação da API do fornecedor" -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "Informações de autenticação" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "Definir a marcação para produtos recuperados desse fornecedor" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "Porcentagem da margem de lucro do fornecedor" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "Nome do fornecedor" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "Nome do fornecedor" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "Identificador de tag interno para a tag do produto" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "Nome da etiqueta" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "Nome de fácil utilização para a etiqueta do produto" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "Nome de exibição da tag" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "Etiqueta do produto" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "tag de categoria" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "tags de categoria" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "Faça upload de uma imagem que represente essa categoria" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "Imagem da categoria" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "Definir uma porcentagem de majoração para os produtos dessa categoria" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "Pai dessa categoria para formar uma estrutura hierárquica" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "Categoria dos pais" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "Nome da categoria" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "Forneça um nome para essa categoria" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "Adicione uma descrição detalhada para essa categoria" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "Descrição da categoria" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "tags que ajudam a descrever ou agrupar essa categoria" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "Prioridade" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "Nome da marca" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "Nome da marca" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "Faça upload de um logotipo que represente essa marca" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "Imagem pequena da marca" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "Faça upload de um logotipo grande que represente essa marca" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "Imagem de marca grande" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "Adicione uma descrição detalhada da marca" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "Descrição da marca" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "Categorias opcionais às quais essa marca está associada" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "Categorias" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "Categoria à qual este produto pertence" - -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "Opcionalmente, associe esse produto a uma marca" - -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "Tags que ajudam a descrever ou agrupar este produto" - -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "Indica se esse produto é entregue digitalmente" - -#: core/models.py:351 -msgid "is product digital" -msgstr "O produto é digital" - -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "Fornecer um nome de identificação claro para o produto" - -#: core/models.py:358 -msgid "product name" -msgstr "Nome do produto" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "Adicione uma descrição detalhada do produto" - -#: core/models.py:364 -msgid "product description" -msgstr "Descrição do produto" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "Número de peça para este produto" - -#: core/models.py:372 -msgid "part number" -msgstr "Número da peça" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "Categoria desse atributo" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "Grupo desse atributo" - -#: core/models.py:465 -msgid "string" -msgstr "Cordas" - -#: core/models.py:466 -msgid "integer" -msgstr "Inteiro" - -#: core/models.py:467 -msgid "float" -msgstr "Flutuação" - -#: core/models.py:468 -msgid "boolean" -msgstr "Booleano" - -#: core/models.py:469 -msgid "array" -msgstr "Matriz" - -#: core/models.py:470 -msgid "object" -msgstr "Objeto" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "Tipo do valor do atributo" - -#: core/models.py:473 -msgid "value type" -msgstr "Tipo de valor" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "Nome desse atributo" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "Nome do atributo" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "Atributo" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "Atributo desse valor" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "O produto específico associado ao valor desse atributo" - -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 -msgid "associated product" -msgstr "Produto associado" - -#: core/models.py:512 -msgid "the specific value for this attribute" -msgstr "O valor específico para esse atributo" - -#: core/models.py:528 -msgid "provide alternative text for the image for accessibility" -msgstr "" -"Forneça um texto alternativo para a imagem para fins de acessibilidade" - -#: core/models.py:529 -msgid "image alt text" -msgstr "Texto alternativo da imagem" - -#: core/models.py:532 -msgid "upload the image file for this product" -msgstr "Faça o upload do arquivo de imagem para este produto" - -#: core/models.py:533 core/models.py:558 -msgid "product image" -msgstr "Imagem do produto" - -#: core/models.py:539 -msgid "determines the order in which images are displayed" -msgstr "Determina a ordem em que as imagens são exibidas" - -#: core/models.py:540 -msgid "display priority" -msgstr "Prioridade de exibição" - -#: core/models.py:545 -msgid "the product that this image represents" -msgstr "O produto que esta imagem representa" - -#: core/models.py:559 -msgid "product images" -msgstr "Imagens do produto" - -#: core/models.py:567 -msgid "percentage discount for the selected products" -msgstr "Desconto percentual para os produtos selecionados" - -#: core/models.py:568 -msgid "discount percentage" -msgstr "Porcentagem de desconto" - -#: core/models.py:573 -msgid "provide a unique name for this promotion" -msgstr "Forneça um nome exclusivo para essa promoção" - -#: core/models.py:574 -msgid "promotion name" -msgstr "Nome da promoção" - -#: core/models.py:580 -msgid "promotion description" -msgstr "Descrição da promoção" - -#: core/models.py:585 -msgid "select which products are included in this promotion" -msgstr "Selecione quais produtos estão incluídos nessa promoção" - -#: core/models.py:586 -msgid "included products" -msgstr "Produtos incluídos" - -#: core/models.py:590 -msgid "promotion" -msgstr "Promoção" - -#: core/models.py:605 +#: core/models.py:515 msgid "the vendor supplying this product stock" msgstr "O fornecedor que fornece esse estoque de produtos" -#: core/models.py:606 +#: core/models.py:516 msgid "associated vendor" msgstr "Fornecedor associado" -#: core/models.py:610 +#: core/models.py:520 msgid "final price to the customer after markups" msgstr "Preço final para o cliente após as marcações" -#: core/models.py:611 +#: core/models.py:521 msgid "selling price" msgstr "Preço de venda" -#: core/models.py:616 +#: core/models.py:526 msgid "the product associated with this stock entry" msgstr "O produto associado a essa entrada em estoque" -#: core/models.py:624 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "Produto associado" + +#: core/models.py:534 msgid "the price paid to the vendor for this product" msgstr "O preço pago ao fornecedor por esse produto" -#: core/models.py:625 +#: core/models.py:535 msgid "vendor purchase price" msgstr "Preço de compra do fornecedor" -#: core/models.py:629 +#: core/models.py:539 msgid "available quantity of the product in stock" msgstr "Quantidade disponível do produto em estoque" -#: core/models.py:630 +#: core/models.py:540 msgid "quantity in stock" msgstr "Quantidade em estoque" -#: core/models.py:634 +#: core/models.py:544 msgid "vendor-assigned SKU for identifying the product" msgstr "SKU atribuído pelo fornecedor para identificar o produto" -#: core/models.py:635 +#: core/models.py:545 msgid "vendor sku" msgstr "SKU do fornecedor" -#: core/models.py:641 +#: core/models.py:551 msgid "digital file associated with this stock if applicable" msgstr "Arquivo digital associado a esse estoque, se aplicável" -#: core/models.py:642 +#: core/models.py:552 msgid "digital file" msgstr "Arquivo digital" -#: core/models.py:651 +#: core/models.py:561 msgid "stock entries" msgstr "Entradas de estoque" -#: core/models.py:660 +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "Categoria à qual este produto pertence" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "Opcionalmente, associe esse produto a uma marca" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "Tags que ajudam a descrever ou agrupar este produto" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "Indica se esse produto é entregue digitalmente" + +#: core/models.py:626 +msgid "is product digital" +msgstr "O produto é digital" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "Fornecer um nome de identificação claro para o produto" + +#: core/models.py:633 +msgid "product name" +msgstr "Nome do produto" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "Adicione uma descrição detalhada do produto" + +#: core/models.py:639 +msgid "product description" +msgstr "Descrição do produto" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "Número de peça para este produto" + +#: core/models.py:647 +msgid "part number" +msgstr "Número da peça" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "Categoria desse atributo" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "Grupo desse atributo" + +#: core/models.py:767 +msgid "string" +msgstr "Cordas" + +#: core/models.py:768 +msgid "integer" +msgstr "Inteiro" + +#: core/models.py:769 +msgid "float" +msgstr "Flutuação" + +#: core/models.py:770 +msgid "boolean" +msgstr "Booleano" + +#: core/models.py:771 +msgid "array" +msgstr "Matriz" + +#: core/models.py:772 +msgid "object" +msgstr "Objeto" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "Tipo do valor do atributo" + +#: core/models.py:775 +msgid "value type" +msgstr "Tipo de valor" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "Nome desse atributo" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "Nome do atributo" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "Atributo" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "Atributo desse valor" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "O produto específico associado ao valor desse atributo" + +#: core/models.py:837 +msgid "the specific value for this attribute" +msgstr "O valor específico para esse atributo" + +#: core/models.py:871 +msgid "provide alternative text for the image for accessibility" +msgstr "Forneça um texto alternativo para a imagem para fins de acessibilidade" + +#: core/models.py:872 +msgid "image alt text" +msgstr "Texto alternativo da imagem" + +#: core/models.py:875 +msgid "upload the image file for this product" +msgstr "Faça o upload do arquivo de imagem para este produto" + +#: core/models.py:876 core/models.py:901 +msgid "product image" +msgstr "Imagem do produto" + +#: core/models.py:882 +msgid "determines the order in which images are displayed" +msgstr "Determina a ordem em que as imagens são exibidas" + +#: core/models.py:883 +msgid "display priority" +msgstr "Prioridade de exibição" + +#: core/models.py:888 +msgid "the product that this image represents" +msgstr "O produto que esta imagem representa" + +#: core/models.py:902 +msgid "product images" +msgstr "Imagens do produto" + +#: core/models.py:943 +msgid "percentage discount for the selected products" +msgstr "Desconto percentual para os produtos selecionados" + +#: core/models.py:944 +msgid "discount percentage" +msgstr "Porcentagem de desconto" + +#: core/models.py:949 +msgid "provide a unique name for this promotion" +msgstr "Forneça um nome exclusivo para essa promoção" + +#: core/models.py:950 +msgid "promotion name" +msgstr "Nome da promoção" + +#: core/models.py:956 +msgid "promotion description" +msgstr "Descrição da promoção" + +#: core/models.py:961 +msgid "select which products are included in this promotion" +msgstr "Selecione quais produtos estão incluídos nessa promoção" + +#: core/models.py:962 +msgid "included products" +msgstr "Produtos incluídos" + +#: core/models.py:966 +msgid "promotion" +msgstr "Promoção" + +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "Produtos que o usuário marcou como desejados" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "Usuário que possui esta lista de desejos" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "Proprietário da lista de desejos" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "Lista de desejos" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} não existe: {product_uuid}" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "Documentário" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "Documentários" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "Não resolvido" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "Linha de endereço do cliente" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "Linha de endereço" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "Rua" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "Distrito" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "Cidade" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "Região" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "Código postal" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "País" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "Ponto de geolocalização (Longitude, Latitude)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "Resposta JSON completa do geocodificador para este endereço" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "Resposta JSON armazenada do serviço de geocodificação" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "Endereço" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "Endereços" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "Código exclusivo usado por um usuário para resgatar um desconto" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "Identificador de código promocional" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "Valor de desconto fixo aplicado se a porcentagem não for usada" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "Valor do desconto fixo" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "Desconto percentual aplicado se o valor fixo não for usado" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "Desconto percentual" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "Registro de data e hora em que o código promocional expira" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "Tempo de validade final" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "" "Registro de data e hora a partir do qual esse código promocional é válido" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "Hora de início da validade" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "" "Registro de data e hora em que o código promocional foi usado, em branco se " "ainda não tiver sido usado" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "Registro de data e hora de uso" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "Usuário atribuído a esse código promocional, se aplicável" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "Usuário atribuído" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "Código promocional" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "Códigos promocionais" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." msgstr "" -"Apenas um tipo de desconto deve ser definido (valor ou porcentagem), mas não" -" ambos ou nenhum." +"Apenas um tipo de desconto deve ser definido (valor ou porcentagem), mas não " +"ambos ou nenhum." -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "O código promocional já foi usado" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "Tipo de desconto inválido para o código promocional {self.uuid}" +msgstr "Tipo de desconto inválido para o código promocional {self.uuid}!" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "O endereço de cobrança usado para esse pedido" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "Código promocional opcional aplicado a este pedido" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "Código promocional aplicado" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "O endereço de entrega usado para esse pedido" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "Endereço de entrega" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "Status atual do pedido em seu ciclo de vida" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "Status do pedido" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" "Estrutura JSON de notificações a serem exibidas aos usuários; na interface " "do usuário do administrador, é usada a visualização de tabela" -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "Representação JSON dos atributos do pedido para esse pedido" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "O usuário que fez o pedido" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "Usuário" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "O registro de data e hora em que o pedido foi finalizado" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "Tempo de compra" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "Um identificador legível por humanos para o pedido" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "ID legível por humanos" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "Pedido" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "Um usuário deve ter apenas uma ordem pendente por vez!" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "Não é possível adicionar produtos a um pedido que não esteja pendente" -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "Não é possível adicionar produtos inativos ao pedido" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "" "Não é possível adicionar mais produtos do que os disponíveis em estoque" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "Não é possível remover produtos de um pedido que não esteja pendente" -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "{name} não existe com a consulta <{query}>" +msgstr "{name} não existe com a consulta <{query}>!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "O código promocional não existe" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "" -"Você só pode comprar produtos físicos com o endereço de entrega " -"especificado!" +"Você só pode comprar produtos físicos com o endereço de entrega especificado!" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "O endereço não existe" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "" "Não é possível comprar neste momento, tente novamente em alguns minutos." -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "Valor de força inválido" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "Você não pode comprar um pedido vazio!" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "Não é possível comprar um pedido sem um usuário!" + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "Um usuário sem saldo não pode comprar com saldo!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "Fundos insuficientes para concluir o pedido" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" @@ -1964,7 +1999,7 @@ msgstr "" "Não é possível comprar sem registro, forneça as seguintes informações: nome " "do cliente, e-mail do cliente, número de telefone do cliente" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" @@ -1972,115 +2007,118 @@ msgstr "" "Método de pagamento inválido: {payment_method} de " "{available_payment_methods}!" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "O preço pago pelo cliente por esse produto no momento da compra" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "Preço de compra no momento do pedido" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "" "Comentários internos para administradores sobre este produto encomendado" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "Comentários internos" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "Notificações do usuário" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "Representação JSON dos atributos desse item" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "Atributos ordenados do produto" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "Referência ao pedido pai que contém esse produto" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "Ordem dos pais" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "O produto específico associado a essa linha de pedido" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "Quantidade desse produto específico no pedido" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "Quantidade do produto" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "Status atual desse produto no pedido" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "Status da linha de produtos" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "O Orderproduct deve ter um pedido associado!" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "ação incorreta especificada para feedback: {action}" +msgstr "Ação incorreta especificada para o feedback: {action}!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "você não pode dar feedback a um pedido que não foi recebido" -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "Baixar" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "Downloads" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "" "Não é possível fazer download de um ativo digital para um pedido não " "concluído" -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "" "Comentários fornecidos pelo usuário sobre sua experiência com o produto" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "Comentários de feedback" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "" -"Faz referência ao produto específico em um pedido sobre o qual se trata esse" -" feedback" +"Faz referência ao produto específico em um pedido sobre o qual se trata esse " +"feedback" -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "Produto de pedido relacionado" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "Classificação atribuída pelo usuário ao produto" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "Avaliação do produto" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "Feedback" @@ -2091,13 +2129,13 @@ msgstr "" "Você deve fornecer um comentário, uma classificação e o uuid do produto do " "pedido para adicionar feedback." -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "Erro durante a criação do código promocional: {e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2106,7 +2144,7 @@ msgid "order confirmation" msgstr "Confirmação de pedido" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2123,21 +2161,22 @@ msgstr "Olá %(order.user.first_name)s," #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" msgstr "" "Obrigado por seu pedido #%(order.pk)s! Temos o prazer de informá-lo de que " "seu pedido foi colocado em prática. Abaixo estão os detalhes de seu pedido:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "Total" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2157,23 +2196,23 @@ msgstr "" #: core/templates/digital_order_created_email.html:133 #, python-format msgid "best regards,
the %(config.PROJECT_NAME)s team" -msgstr "Com os melhores cumprimentos,
da equipe de %(config.PROJECT_NAME)s" +msgstr "Atenciosamente,
a equipe %(config.PROJECT_NAME)s" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "Todos os direitos reservados" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "Pedido entregue" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "Olá %(user_first_name)s," -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" @@ -2182,7 +2221,7 @@ msgstr "" "Seu pedido №%(order_uuid)s foi processado com sucesso! Abaixo estão os " "detalhes de seu pedido:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2190,12 +2229,12 @@ msgstr "" "adicionais\n" " informações adicionais" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "Valor" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -2204,10 +2243,10 @@ msgstr "" "Se tiver alguma dúvida, entre em contato com nosso suporte em " "%(contact_email)s." -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Atenciosamente,
a equipe de %(project_name)s" +msgstr "Atenciosamente,
a equipe %(project_name)s" #: core/templates/json_table_widget.html:5 msgid "key" @@ -2216,7 +2255,8 @@ msgstr "Chave" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" msgstr "" "Obrigado por seu pedido! Temos o prazer de confirmar sua compra. Abaixo " @@ -2236,7 +2276,7 @@ msgstr "Seu pedido será entregue no seguinte endereço:" #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "Com os melhores cumprimentos,
a equipe de %(config.PROJECT_NAME)s" +msgstr "Com os melhores cumprimentos,
A equipe %(config.PROJECT_NAME)s" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2255,30 +2295,20 @@ msgstr "São necessários dados e tempo limite" msgid "invalid timeout value, it must be between 0 and 216000 seconds" msgstr "Valor de tempo limite inválido, deve estar entre 0 e 216000 segundos" -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model} deve ser o modelo" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data} deve ser um objeto de lista" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | Entre em contato conosco iniciado" +msgstr "{config.PROJECT_NAME} | entre em contato conosco iniciado" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" -msgstr "{config.PROJECT_NAME} | Confirmação de pedido" +msgstr "{config.PROJECT_NAME} | Confirmação do pedido" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" -msgstr "{config.PROJECT_NAME} | Order Delivered" +msgstr "{config.PROJECT_NAME} | Pedido entregue" #: core/utils/messages.py:3 msgid "you do not have permission to perform this action." @@ -2298,15 +2328,15 @@ msgstr "" msgid "invalid phone number format" msgstr "Formato de número telefônico inválido" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "Você só pode fazer o download do ativo digital uma vez" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "favicon não encontrado" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "Erro de geocodificação: {e}" diff --git a/core/locale/ro_RO/LC_MESSAGES/django.mo b/core/locale/ro_RO/LC_MESSAGES/django.mo index 3c7a6afd..0bc23179 100644 Binary files a/core/locale/ro_RO/LC_MESSAGES/django.mo and b/core/locale/ro_RO/LC_MESSAGES/django.mo differ diff --git a/core/locale/ro_RO/LC_MESSAGES/django.po b/core/locale/ro_RO/LC_MESSAGES/django.po index 73985fcd..2871dd1e 100644 --- a/core/locale/ro_RO/LC_MESSAGES/django.po +++ b/core/locale/ro_RO/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,122 +13,119 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "ID unic" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "" "ID-ul unic este utilizat pentru a identifica cu siguranță orice obiect din " "baza de date" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "Este activ" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" +"if set to false, this object can't be seen by users without needed permission" msgstr "" -"Dacă este setat la false, acest obiect nu poate fi văzut de utilizatori fără" -" permisiunea necesară" +"Dacă este setat la false, acest obiect nu poate fi văzut de utilizatori fără " +"permisiunea necesară" -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "Creat" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "Când a apărut pentru prima dată obiectul în baza de date" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "Modificat" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "Când a fost editat obiectul ultima dată" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "Traduceri" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "Generalități" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "Relații" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "Metadate" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "Timestamps" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" -msgstr "Activați %(verbose_name_plural)s selectate" +msgstr "Activați %(verbose_name_plural)s selectat" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)s activat cu succes!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "Articolele selectate au fost activate!" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" -msgstr "Dezactivați %(verbose_name_plural)s selectate" +msgstr "Dezactivați %(verbose_name_plural)s selectat" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "%(verbose_name_plural)s dezactivat cu succes." +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "Articolele selectate au fost dezactivate!" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "Atribut Valoare" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "Valori ale atributului" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "Imagine" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "Imagini" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "Stoc" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "Stocuri" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "Comanda Produs" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "Comandați produse" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "Copii" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "Configurare" @@ -180,7 +177,7 @@ msgstr "Momental" msgid "successful" msgstr "De succes" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "Cache I/O" @@ -190,7 +187,8 @@ msgid "" "apply key, data and timeout with authentication to write data to cache." msgstr "" "Aplicați doar o cheie pentru a citi datele permise din cache.\n" -"Aplicați o cheie, date și timeout cu autentificare pentru a scrie date în cache." +"Aplicați o cheie, date și timeout cu autentificare pentru a scrie date în " +"cache." #: core/docs/drf/views.py:32 msgid "get a list of supported languages" @@ -204,15 +202,15 @@ msgstr "Obțineți parametrii expunibili ai aplicației" msgid "send a message to the support team" msgstr "Trimiteți un mesaj echipei de asistență" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "Solicitați un URL CORSed. Numai https este permis." #: core/docs/drf/views.py:85 msgid "global search endpoint to query across project's tables" msgstr "" -"Punct final de căutare globală pentru a efectua interogări în toate tabelele" -" proiectului" +"Punct final de căutare globală pentru a efectua interogări în toate tabelele " +"proiectului" #: core/docs/drf/views.py:91 msgid "purchase an order as a business" @@ -223,8 +221,8 @@ msgid "" "purchase an order as a business, using the provided `products` with " "`product_uuid` and `attributes`." msgstr "" -"Achiziționați o comandă ca o afacere, utilizând `products` cu `product_uuid`" -" și `attributes` furnizate." +"Achiziționați o comandă ca o afacere, utilizând `products` cu `product_uuid` " +"și `attributes` furnizate." #: core/docs/drf/viewsets.py:43 msgid "list all attribute groups (simple view)" @@ -245,12 +243,10 @@ msgstr "Ștergerea unui grup de atribute" #: core/docs/drf/viewsets.py:59 msgid "rewrite an existing attribute group saving non-editables" msgstr "" -"Rescrierea unui grup de atribute existent cu salvarea elementelor " -"needitabile" +"Rescrierea unui grup de atribute existent cu salvarea elementelor needitabile" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" +msgid "rewrite some fields of an existing attribute group saving non-editables" msgstr "" "Rescrierea unor câmpuri ale unui grup de atribute existent, cu salvarea " "elementelor needitabile" @@ -303,8 +299,7 @@ msgstr "" "Rescrierea unei valori de atribut existente care salvează non-editabile" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" +msgid "rewrite some fields of an existing attribute value saving non-editables" msgstr "" "Rescrierea unor câmpuri ale unei valori de atribut existente salvând " "elementele needitabile" @@ -347,8 +342,8 @@ msgstr "" #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" "Căutare de substring insensibilă la majuscule în human_readable_id, " "order_products.product.name și order_products.product.partnumber" @@ -387,9 +382,9 @@ msgstr "" #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" "Ordonați după unul dintre: uuid, human_readable_id, user_email, user, " "status, created, modified, buy_time, random. Prefixați cu \"-\" pentru " @@ -435,7 +430,7 @@ msgstr "" "achiziția este finalizată utilizând soldul utilizatorului; Dacă se " "utilizează `force_payment`, este inițiată o tranzacție." -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "achiziționarea unei comenzi fără crearea unui cont" @@ -571,18 +566,29 @@ msgstr "" msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "Filtrați după una sau mai multe perechi nume de atribut/valoare. \n" "- **Sintaxa**: `attr_name=method-value[;attr2=method2-value2]...`\n" -"- **Metode** (valoarea implicită este `icontains` dacă este omisă): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`\n" -"- **Value typing**: JSON este încercat în primul rând (astfel încât să puteți trece liste/dicte), `true`/`false` pentru booleeni, întregi, float; în caz contrar tratat ca string. \n" -"- **Base64**: prefix cu `b64-` pentru a codifica valoarea brută în baza64 în condiții de siguranță URL. \n" +"- **Metode** (valoarea implicită este `icontains` dacă este omisă): " +"`iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, " +"`istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, " +"`gt`, `gte`, `in`\n" +"- **Value typing**: JSON este încercat în primul rând (astfel încât să " +"puteți trece liste/dicte), `true`/`false` pentru booleeni, întregi, float; " +"în caz contrar tratat ca string. \n" +"- **Base64**: prefix cu `b64-` pentru a codifica valoarea brută în baza64 în " +"condiții de siguranță URL. \n" "Exemple: \n" "`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`,\n" "`b64-description=icontains-aGVhdC1jb2xk`" @@ -637,10 +643,12 @@ msgstr "(exact) Digital vs. fizic" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" -"Lista de câmpuri separate prin virgulă după care se face sortarea. Prefixați cu `-` pentru descrescător. \n" +"Lista de câmpuri separate prin virgulă după care se face sortarea. Prefixați " +"cu `-` pentru descrescător. \n" "**Autorizate:** uuid, rating, nume, slug, creat, modificat, preț, aleatoriu" #: core/docs/drf/viewsets.py:441 @@ -708,8 +716,8 @@ msgstr "Autocompletare adresă de intrare" #: core/docs/drf/viewsets.py:576 msgid "raw data query string, please append with data from geo-IP endpoint" msgstr "" -"docker compose exec app poetry run python manage.py deepl_translate -l en-gb" -" -l ar-ar -l cs-cz -l da-dk -l de-de -l en-us -l es-es -l fr-fr -l hi-in -l " +"docker compose exec app poetry run python manage.py deepl_translate -l en-gb " +"-l ar-ar -l cs-cz -l da-dk -l de-de -l en-us -l es-es -l fr-fr -l hi-in -l " "it-it -l ja-jp -l kk-kz -l nl-nl -l pl-pl -l pt-br -l ro-ro -l ru-ru -l zh-" "hans -a core -a geo -a plăți -a vibes_auth -a blog" @@ -771,7 +779,7 @@ msgstr "ștergeți o relație comandă-produs" msgid "add or remove feedback on an order–product relation" msgstr "adăugarea sau eliminarea feedback-ului într-o relație comandă-produs" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "Nu a fost furnizat niciun termen de căutare." @@ -819,8 +827,8 @@ msgstr "Atribute" msgid "Quantity" msgstr "Cantitate" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "Melc" @@ -883,219 +891,242 @@ msgstr "Nivel" msgid "Product UUID" msgstr "UUID produs" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "Cheie care trebuie căutată sau introdusă în cache" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "Date de stocat în cache" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "Timeout în secunde pentru a seta datele în cache" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "Date în cache" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "Date JSON Camelizate de la URL-ul solicitat" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "Sunt permise numai URL-urile care încep cu http(s)://" -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "Adăugați un produs la comandă" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "Comanda {order_uuid} nu a fost găsită" +msgstr "Comanda {order_uuid} nu a fost găsită!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "Eliminați un produs din comandă" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "Eliminați toate produsele din comandă" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "Cumpărați o comandă" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "" "Vă rugăm să furnizați fie order_uuid sau order_hr_id - se exclud reciproc!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "Metoda order.buy() a generat un tip greșit: {type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "Efectuați o acțiune asupra unei liste de produse din comandă" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "Eliminare/adăugare" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "Acțiunea trebuie să fie fie \"adăugare\" sau \"eliminare\"!" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "Efectuați o acțiune pe o listă de produse din lista de dorințe" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "Vă rugăm să furnizați valoarea `wishlist_uuid`." + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "Wishlist {wishlist_uuid} nu a fost găsit!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "Adăugați un produs la comandă" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "Lista dorințelor {wishlist_uuid} nu a fost găsită" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "Eliminați un produs din comandă" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "Eliminați un produs din comandă" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "Eliminați un produs din comandă" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "Cumpărați o comandă" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" msgstr "" "Vă rugăm să trimiteți atributele sub formă de șir format ca attr1=valoare1, " "attr2=valoare2" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "Adăugați sau ștergeți un feedback pentru comandaprodus" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "Acțiunea trebuie să fie `add` sau `remove`!" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "Comandaprodus {order_product_uuid} nu a fost găsită!" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "Șirul de adrese original furnizat de utilizator" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} nu există: {uuid}" +msgstr "{name} nu există: {uuid}!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "Limita trebuie să fie între 1 și 10" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - funcționează ca un farmec" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "Atribute" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "Atribute grupate" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "Grupuri de atribute" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "Categorii" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "Mărci" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "Categorii" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "Procentul de majorare" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "" "Atributele și valorile care pot fi utilizate pentru filtrarea acestei " "categorii." -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." -msgstr "" -"Prețurile minime și maxime pentru produsele din această categorie, dacă sunt" -" disponibile." - #: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." +msgstr "" +"Prețurile minime și maxime pentru produsele din această categorie, dacă sunt " +"disponibile." + +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "Etichete pentru această categorie" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "Produse din această categorie" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "Furnizori" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "Latitudine (coordonata Y)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "Longitudine (coordonata X)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "Cum să" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "Valoare nominală de la 1 la 10, inclusiv, sau 0 dacă nu este setată." -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "Reprezintă feedback de la un utilizator." -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "Notificări" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "URL de descărcare pentru acest produs de comandă, dacă este cazul" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "O listă a produselor comandate în această comandă" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "Adresa de facturare" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" @@ -1103,736 +1134,732 @@ msgstr "" "Adresa de expediere pentru această comandă, lăsați în alb dacă este aceeași " "cu adresa de facturare sau dacă nu se aplică" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "Prețul total al acestei comenzi" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "Cantitatea totală de produse din comandă" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "Sunt toate produsele din comanda digitală" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "Tranzacții pentru această comandă" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "Ordine" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "URL imagine" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "Imagini ale produsului" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "Categorie" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "Feedback-uri" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "Marca" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "Grupuri de atribute" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "Preț" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "Cantitate" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "Numărul de reacții" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "Produse" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "Coduri promoționale" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "Produse scoase la vânzare" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "Promoții" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "Furnizor" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "Produs" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "Produse dorite" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "Liste de dorințe" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "Produse etichetate" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "Etichete de produs" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "Categorii etichetate" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "Etichete \"Categorii" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "Numele proiectului" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "Email companie" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "Numele companiei" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "Adresa companiei" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "Numărul de telefon al companiei" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "" "\"e-mail de la\", uneori trebuie să fie utilizat în locul valorii " "utilizatorului gazdă" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "Utilizator gazdă e-mail" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "Suma maximă pentru plată" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "Suma minimă pentru plată" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "Date analitice" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "Date publicitare" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "Configurație" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "Codul limbii" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "Numele limbii" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "Indicatorul de limbă, dacă există :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "Obțineți o listă a limbilor acceptate" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "Rezultate căutare produse" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "Rezultate căutare produse" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "Părinte al acestui grup" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "Grup de atribute părinte" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "Numele grupului de atribute" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "Grup de atribute" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" "Stochează acreditările și punctele finale necesare pentru comunicarea API a " "furnizorului" -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "Informații privind autentificarea" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "" "Definirea marjei de profit pentru produsele preluate de la acest furnizor" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "Procentul de majorare al furnizorului" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "Numele acestui vânzător" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "Numele furnizorului" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "Identificator intern de etichetă pentru eticheta produsului" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "Nume etichetă" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "Nume ușor de utilizat pentru eticheta produsului" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "Nume afișare etichetă" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "Etichetă produs" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "etichetă de categorie" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "Etichete de categorie" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "Încărcați o imagine care reprezintă această categorie" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "Categorie imagine" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" -msgstr "" -"Definiți un procent de majorare pentru produsele din această categorie" +msgstr "Definiți un procent de majorare pentru produsele din această categorie" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "Părinte al acestei categorii pentru a forma o structură ierarhică" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "Categoria de părinți" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "Numele categoriei" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "Furnizați un nume pentru această categorie" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "Adăugați o descriere detaliată pentru această categorie" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "Descriere categorie" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "etichete care ajută la descrierea sau gruparea acestei categorii" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "Prioritate" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "Denumirea acestui brand" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "Nume de marcă" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "Încărcați un logo care reprezintă acest brand" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "Brand imagine mică" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "Încărcați un logo mare care reprezintă acest brand" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "Imagine de marcă mare" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "Adăugați o descriere detaliată a mărcii" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "Descrierea mărcii" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "Categorii opționale cu care acest brand este asociat" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "Categorii" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "Categoria din care face parte acest produs" - -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "Opțional, asociați acest produs cu un brand" - -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "Etichete care ajută la descrierea sau gruparea acestui produs" - -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "Indică dacă acest produs este livrat digital" - -#: core/models.py:351 -msgid "is product digital" -msgstr "Produsul este digital" - -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "Furnizați o denumire clară de identificare a produsului" - -#: core/models.py:358 -msgid "product name" -msgstr "Denumirea produsului" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "Adăugați o descriere detaliată a produsului" - -#: core/models.py:364 -msgid "product description" -msgstr "Descrierea produsului" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "Numărul piesei pentru acest produs" - -#: core/models.py:372 -msgid "part number" -msgstr "Numărul piesei" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "Categoria acestui atribut" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "Grupul acestui atribut" - -#: core/models.py:465 -msgid "string" -msgstr "Șir de caractere" - -#: core/models.py:466 -msgid "integer" -msgstr "Număr întreg" - -#: core/models.py:467 -msgid "float" -msgstr "Float" - -#: core/models.py:468 -msgid "boolean" -msgstr "Boolean" - -#: core/models.py:469 -msgid "array" -msgstr "Array" - -#: core/models.py:470 -msgid "object" -msgstr "Obiect" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "Tipul valorii atributului" - -#: core/models.py:473 -msgid "value type" -msgstr "Tipul de valoare" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "Denumirea acestui atribut" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "Numele atributului" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "Atribut" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "Atributul acestei valori" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "Produsul specific asociat cu valoarea acestui atribut" - -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 -msgid "associated product" -msgstr "Produs asociat" - -#: core/models.py:512 -msgid "the specific value for this attribute" -msgstr "Valoarea specifică pentru acest atribut" - -#: core/models.py:528 -msgid "provide alternative text for the image for accessibility" -msgstr "Furnizați text alternativ pentru imagine pentru accesibilitate" - -#: core/models.py:529 -msgid "image alt text" -msgstr "Textul alt al imaginii" - -#: core/models.py:532 -msgid "upload the image file for this product" -msgstr "Încărcați fișierul de imagine pentru acest produs" - -#: core/models.py:533 core/models.py:558 -msgid "product image" -msgstr "Imaginea produsului" - -#: core/models.py:539 -msgid "determines the order in which images are displayed" -msgstr "Determină ordinea în care sunt afișate imaginile" - -#: core/models.py:540 -msgid "display priority" -msgstr "Prioritatea afișării" - -#: core/models.py:545 -msgid "the product that this image represents" -msgstr "Produsul pe care îl reprezintă această imagine" - -#: core/models.py:559 -msgid "product images" -msgstr "Imagini ale produsului" - -#: core/models.py:567 -msgid "percentage discount for the selected products" -msgstr "Procentul de reducere pentru produsele selectate" - -#: core/models.py:568 -msgid "discount percentage" -msgstr "Procent de reducere" - -#: core/models.py:573 -msgid "provide a unique name for this promotion" -msgstr "Furnizați un nume unic pentru această promoție" - -#: core/models.py:574 -msgid "promotion name" -msgstr "Numele promoției" - -#: core/models.py:580 -msgid "promotion description" -msgstr "Descrierea promoției" - -#: core/models.py:585 -msgid "select which products are included in this promotion" -msgstr "Selectați ce produse sunt incluse în această promoție" - -#: core/models.py:586 -msgid "included products" -msgstr "Produse incluse" - -#: core/models.py:590 -msgid "promotion" -msgstr "Promovare" - -#: core/models.py:605 +#: core/models.py:515 msgid "the vendor supplying this product stock" msgstr "Furnizorul care furnizează acest stoc de produse" -#: core/models.py:606 +#: core/models.py:516 msgid "associated vendor" msgstr "Furnizor asociat" -#: core/models.py:610 +#: core/models.py:520 msgid "final price to the customer after markups" msgstr "Prețul final pentru client după majorări" -#: core/models.py:611 +#: core/models.py:521 msgid "selling price" msgstr "Prețul de vânzare" -#: core/models.py:616 +#: core/models.py:526 msgid "the product associated with this stock entry" msgstr "Produsul asociat cu această intrare în stoc" -#: core/models.py:624 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "Produs asociat" + +#: core/models.py:534 msgid "the price paid to the vendor for this product" msgstr "Prețul plătit vânzătorului pentru acest produs" -#: core/models.py:625 +#: core/models.py:535 msgid "vendor purchase price" msgstr "Prețul de achiziție al furnizorului" -#: core/models.py:629 +#: core/models.py:539 msgid "available quantity of the product in stock" msgstr "Cantitatea disponibilă a produsului în stoc" -#: core/models.py:630 +#: core/models.py:540 msgid "quantity in stock" msgstr "Cantitate în stoc" -#: core/models.py:634 +#: core/models.py:544 msgid "vendor-assigned SKU for identifying the product" msgstr "SKU atribuit de furnizor pentru identificarea produsului" -#: core/models.py:635 +#: core/models.py:545 msgid "vendor sku" msgstr "SKU al furnizorului" -#: core/models.py:641 +#: core/models.py:551 msgid "digital file associated with this stock if applicable" msgstr "Fișier digital asociat cu acest stoc, dacă este cazul" -#: core/models.py:642 +#: core/models.py:552 msgid "digital file" msgstr "Fișier digital" -#: core/models.py:651 +#: core/models.py:561 msgid "stock entries" msgstr "Intrări pe stoc" -#: core/models.py:660 +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "Categoria din care face parte acest produs" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "Opțional, asociați acest produs cu un brand" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "Etichete care ajută la descrierea sau gruparea acestui produs" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "Indică dacă acest produs este livrat digital" + +#: core/models.py:626 +msgid "is product digital" +msgstr "Produsul este digital" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "Furnizați o denumire clară de identificare a produsului" + +#: core/models.py:633 +msgid "product name" +msgstr "Denumirea produsului" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "Adăugați o descriere detaliată a produsului" + +#: core/models.py:639 +msgid "product description" +msgstr "Descrierea produsului" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "Numărul piesei pentru acest produs" + +#: core/models.py:647 +msgid "part number" +msgstr "Numărul piesei" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "Categoria acestui atribut" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "Grupul acestui atribut" + +#: core/models.py:767 +msgid "string" +msgstr "Șir de caractere" + +#: core/models.py:768 +msgid "integer" +msgstr "Număr întreg" + +#: core/models.py:769 +msgid "float" +msgstr "Float" + +#: core/models.py:770 +msgid "boolean" +msgstr "Boolean" + +#: core/models.py:771 +msgid "array" +msgstr "Array" + +#: core/models.py:772 +msgid "object" +msgstr "Obiect" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "Tipul valorii atributului" + +#: core/models.py:775 +msgid "value type" +msgstr "Tipul de valoare" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "Denumirea acestui atribut" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "Numele atributului" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "Atribut" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "Atributul acestei valori" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "Produsul specific asociat cu valoarea acestui atribut" + +#: core/models.py:837 +msgid "the specific value for this attribute" +msgstr "Valoarea specifică pentru acest atribut" + +#: core/models.py:871 +msgid "provide alternative text for the image for accessibility" +msgstr "Furnizați text alternativ pentru imagine pentru accesibilitate" + +#: core/models.py:872 +msgid "image alt text" +msgstr "Textul alt al imaginii" + +#: core/models.py:875 +msgid "upload the image file for this product" +msgstr "Încărcați fișierul de imagine pentru acest produs" + +#: core/models.py:876 core/models.py:901 +msgid "product image" +msgstr "Imaginea produsului" + +#: core/models.py:882 +msgid "determines the order in which images are displayed" +msgstr "Determină ordinea în care sunt afișate imaginile" + +#: core/models.py:883 +msgid "display priority" +msgstr "Prioritatea afișării" + +#: core/models.py:888 +msgid "the product that this image represents" +msgstr "Produsul pe care îl reprezintă această imagine" + +#: core/models.py:902 +msgid "product images" +msgstr "Imagini ale produsului" + +#: core/models.py:943 +msgid "percentage discount for the selected products" +msgstr "Procentul de reducere pentru produsele selectate" + +#: core/models.py:944 +msgid "discount percentage" +msgstr "Procent de reducere" + +#: core/models.py:949 +msgid "provide a unique name for this promotion" +msgstr "Furnizați un nume unic pentru această promoție" + +#: core/models.py:950 +msgid "promotion name" +msgstr "Numele promoției" + +#: core/models.py:956 +msgid "promotion description" +msgstr "Descrierea promoției" + +#: core/models.py:961 +msgid "select which products are included in this promotion" +msgstr "Selectați ce produse sunt incluse în această promoție" + +#: core/models.py:962 +msgid "included products" +msgstr "Produse incluse" + +#: core/models.py:966 +msgid "promotion" +msgstr "Promovare" + +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "Produse pe care utilizatorul le-a marcat ca fiind dorite" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "Utilizatorul care deține această listă de dorințe" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "Proprietarul listei de dorințe" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "Lista dorințelor" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} nu există: {product_uuid}" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "Documentar" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "Documentare" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "Nerezolvat" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "Linia de adresă pentru client" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "Linia de adresă" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "Strada" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "Districtul" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "Oraș" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "Regiunea" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "Cod poștal" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "Țara" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "Punct de geolocație (longitudine, latitudine)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "Răspuns JSON complet de la geocoder pentru această adresă" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "Răspuns JSON stocat de la serviciul de geocodare" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "Adresă" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "Adrese" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "Cod unic utilizat de un utilizator pentru a răscumpăra o reducere" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "Cod promoțional de identificare" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "Valoarea fixă a reducerii aplicate dacă procentul nu este utilizat" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "Valoarea fixă a reducerii" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "Procentul de reducere aplicat dacă suma fixă nu este utilizată" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "Reducere procentuală" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "Data la care expiră codul promoțional" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "Timpul final de valabilitate" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "Timestamp de la care acest cod promoțional este valabil" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "Ora de începere a valabilității" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "" "Momentul în care codul promoțional a fost utilizat, gol dacă nu a fost " "utilizat încă" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "Timestamp de utilizare" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "Utilizatorul atribuit acestui cod promoțional, dacă este cazul" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "Utilizator atribuit" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "Cod promoțional" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "Coduri promoționale" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." @@ -1840,140 +1867,149 @@ msgstr "" "Trebuie definit un singur tip de reducere (sumă sau procent), dar nu ambele " "sau niciuna." -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "Codul promoțional a fost deja utilizat" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "Tip de reducere invalid pentru codul promoțional {self.uuid}" +msgstr "Tip de reducere invalid pentru codul promoțional {self.uuid}!" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "Adresa de facturare utilizată pentru această comandă" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "Cod promoțional opțional aplicat la această comandă" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "Cod promoțional aplicat" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "Adresa de expediere utilizată pentru această comandă" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "Adresa de expediere" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "Stadiul actual al comenzii în ciclul său de viață" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "Stadiul comenzii" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" "Structura JSON a notificărilor care urmează să fie afișate utilizatorilor, " "în interfața de administrare este utilizată vizualizarea tabelară" -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "Reprezentarea JSON a atributelor comenzii pentru această comandă" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "Utilizatorul care a plasat comanda" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "Utilizator" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "Momentul în care comanda a fost finalizată" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "Cumpărați timp" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "Un identificator ușor de citit pentru comandă" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "ID lizibil de către om" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "Comandă" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "" "Un utilizator trebuie să aibă un singur ordin în așteptare la un moment dat!" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "Nu puteți adăuga produse la o comandă care nu este în așteptare" -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "Nu puteți adăuga produse inactive la comandă" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "Nu puteți adăuga mai multe produse decât cele disponibile în stoc" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "" "Nu puteți elimina produse dintr-o comandă care nu este o comandă în curs" -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "{name} nu există cu interogarea <{query}>" +msgstr "{name} nu există cu interogarea <{query}>!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "Codul promoțional nu există" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "" "Puteți cumpăra numai produse fizice cu adresa de expediere specificată!" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "Adresa nu există" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "" "Nu puteți achiziționa în acest moment, vă rugăm să încercați din nou în " "câteva minute." -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "Valoare forță invalidă" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "Nu puteți achiziționa o comandă goală!" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "" +"Nu puteți elimina produse dintr-o comandă care nu este o comandă în curs" + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "Un utilizator fără sold nu poate cumpăra cu sold!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "Insuficiența fondurilor pentru finalizarea comenzii" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" @@ -1981,122 +2017,124 @@ msgstr "" "nu puteți cumpăra fără înregistrare, vă rugăm să furnizați următoarele " "informații: nume client, e-mail client, număr de telefon client" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" msgstr "" -"Metodă de plată invalidă: {payment_method} de la " -"{available_payment_methods}!" +"Metodă de plată invalidă: {payment_method} de la {available_payment_methods}!" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "Prețul plătit de client pentru acest produs la momentul achiziției" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "Prețul de achiziție la momentul comenzii" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "" "Comentarii interne pentru administratori cu privire la acest produs comandat" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "Observații interne" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "Notificări pentru utilizatori" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "Reprezentarea JSON a atributelor acestui element" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "Atribute de produs ordonate" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "Trimitere la comanda mamă care conține acest produs" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "Ordinul părinților" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "Produsul specific asociat cu această linie de comandă" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "Cantitatea acestui produs specific din comandă" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "Cantitatea produsului" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "Starea actuală a acestui produs în comandă" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "Starea liniei de produse" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "Comandaprodusul trebuie să aibă o comandă asociată!" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "acțiune greșită specificată pentru feedback: {action}" +msgstr "Acțiune greșită specificată pentru feedback: {action}!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "" "Nu puteți elimina produse dintr-o comandă care nu este o comandă în curs" -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "Descărcare" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "Descărcări" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "Nu puteți descărca un bun digital pentru o comandă nefinalizată" -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "" "Comentarii furnizate de utilizatori cu privire la experiența lor cu produsul" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "Comentarii de feedback" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "" -"Face referire la produsul specific dintr-o comandă despre care este vorba în" -" acest feedback" +"Face referire la produsul specific dintr-o comandă despre care este vorba în " +"acest feedback" -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "Produs aferent comenzii" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "Rating atribuit de utilizator pentru produs" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "Evaluarea produsului" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "Feedback" @@ -2104,16 +2142,16 @@ msgstr "Feedback" msgid "" "you must provide a comment, rating, and order product uuid to add feedback." msgstr "" -"trebuie să furnizați un comentariu, un rating și uuid-ul produsului comandat" -" pentru a adăuga feedback." +"trebuie să furnizați un comentariu, un rating și uuid-ul produsului comandat " +"pentru a adăuga feedback." -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "Eroare în timpul creării codului promoțional: {e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2122,7 +2160,7 @@ msgid "order confirmation" msgstr "Confirmarea comenzii" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2139,7 +2177,8 @@ msgstr "Bună ziua %(order.user.first_name)s," #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" msgstr "" "Vă mulțumim pentru comanda dvs. #%(order.pk)s! Suntem încântați să vă " @@ -2147,14 +2186,14 @@ msgstr "" "comenzii dvs:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "Total" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2174,23 +2213,23 @@ msgstr "" #: core/templates/digital_order_created_email.html:133 #, python-format msgid "best regards,
the %(config.PROJECT_NAME)s team" -msgstr "Salutări,
echipa %(config.PROJECT_NAME)s" +msgstr "Cele mai bune salutări,
echipa %(config.PROJECT_NAME)s" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "Toate drepturile rezervate" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "Comanda livrată" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," msgstr "Bună ziua %(user_first_name)s," -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" @@ -2199,7 +2238,7 @@ msgstr "" "Am procesat cu succes comanda dvs. №%(order_uuid)s! Mai jos sunt detaliile " "comenzii dvs:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2207,12 +2246,12 @@ msgstr "" "informații suplimentare\n" " informații suplimentare" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "Valoare" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -2221,7 +2260,7 @@ msgstr "" "Dacă aveți întrebări, nu ezitați să contactați asistența noastră la " "%(contact_email)s." -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Cele mai bune salutări,
echipa %(project_name)s" @@ -2233,11 +2272,12 @@ msgstr "Cheie" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" msgstr "" -"Vă mulțumim pentru comanda dvs.! Suntem încântați să vă confirmăm achiziția." -" Mai jos sunt detaliile comenzii dvs:" +"Vă mulțumim pentru comanda dvs.! Suntem încântați să vă confirmăm achiziția. " +"Mai jos sunt detaliile comenzii dvs:" #: core/templates/shipped_order_created_email.html:123 #: core/templates/shipped_order_delivered_email.html:123 @@ -2253,7 +2293,7 @@ msgstr "Comanda dvs. va fi livrată la următoarea adresă:" #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "Salutări,
echipa %(config.PROJECT_NAME)s" +msgstr "Salutări,
Echipa %(config.PROJECT_NAME)s" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2272,30 +2312,20 @@ msgstr "Sunt necesare atât datele, cât și timpul de așteptare" msgid "invalid timeout value, it must be between 0 and 216000 seconds" msgstr "Valoare timeout invalidă, trebuie să fie între 0 și 216000 secunde" -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model} trebuie să fie model" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data} trebuie să fie un obiect listă" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | Contactați-ne inițiat" +msgstr "{config.PROJECT_NAME} | contactați-ne inițiat" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" msgstr "{config.PROJECT_NAME} | Confirmarea comenzii" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" -msgstr "{config.PROJECT_NAME} | Comanda livrată" +msgstr "{config.PROJECT_NAME} | Livrarea comenzii" #: core/utils/messages.py:3 msgid "you do not have permission to perform this action." @@ -2316,15 +2346,15 @@ msgstr "" msgid "invalid phone number format" msgstr "Format invalid al numărului de telefon" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "Puteți descărca activul digital o singură dată" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "favicon nu a fost găsit" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "Eroare de geocodare: {e}" diff --git a/core/locale/ru_RU/LC_MESSAGES/django.mo b/core/locale/ru_RU/LC_MESSAGES/django.mo index 2bc8cb1b..b5fd4df8 100644 Binary files a/core/locale/ru_RU/LC_MESSAGES/django.mo and b/core/locale/ru_RU/LC_MESSAGES/django.mo differ diff --git a/core/locale/ru_RU/LC_MESSAGES/django.po b/core/locale/ru_RU/LC_MESSAGES/django.po index e496d6da..a5c17d17 100644 --- a/core/locale/ru_RU/LC_MESSAGES/django.po +++ b/core/locale/ru_RU/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,128 +13,125 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "Уникальный идентификатор" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "" "Уникальный идентификатор используется для точной идентификации любого " "объекта базы данных" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "Активен" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" +"if set to false, this object can't be seen by users without needed permission" msgstr "" "Если установлено значение false, этот объект не может быть виден " "пользователям без необходимого разрешения" -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "Создано" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "Когда объект впервые появился в базе данных" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "Модифицированный" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "Когда объект был отредактирован в последний раз" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "Переводы" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "Общие сведения" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "Отношения" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "Метаданные" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "Временные метки" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" -msgstr "Активировать выбранные %(verbose_name_plural)s" +msgstr "Активировать выбранный %(verbose_name_plural)s" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)s успешно активирован!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "Выбранные сущности активированы!" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" -msgstr "Деактивировать выбранные %(verbose_name_plural)s" +msgstr "Деактивировать выбранный %(verbose_name_plural)s" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "%(verbose_name_plural)s успешно деактивирован." +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "Выбранные сущности были деактивированы!" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "Значение атрибута" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "Значения атрибутов" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "Изображение" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "Изображения" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "Наличие" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "Наличия" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" -msgstr "Заказать товар" +msgstr "Заказанный товар" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" -msgstr "Заказать товары" +msgstr "Заказанные товары" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "Дети" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "Конфигурация" #: core/apps.py:8 msgid "core" -msgstr "Ядро" +msgstr "Главное" #: core/choices.py:4 core/choices.py:20 msgid "finished" @@ -180,7 +177,7 @@ msgstr "Моментальный" msgid "successful" msgstr "Успешный" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "Ввод/вывод кэша" @@ -204,7 +201,7 @@ msgstr "Получите параметры приложения, которые msgid "send a message to the support team" msgstr "Отправьте сообщение в службу поддержки" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "Запросите URL-адрес с поддержкой CORS. Допускается только https." @@ -248,8 +245,7 @@ msgstr "" "элементов" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" +msgid "rewrite some fields of an existing attribute group saving non-editables" msgstr "" "Переписывание некоторых полей существующей группы атрибутов с сохранением " "нередактируемых полей" @@ -303,8 +299,7 @@ msgstr "" "значений" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" +msgid "rewrite some fields of an existing attribute value saving non-editables" msgstr "" "Переписывание некоторых полей существующего значения атрибута с сохранением " "нередактируемых значений" @@ -348,11 +343,11 @@ msgstr "" #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" -"Поиск подстроки с учетом регистра в human_readable_id, " -"order_products.product.name и order_products.product.partnumber" +"Поиск подстроки с учетом регистра в human_readable_id, order_products." +"product.name и order_products.product.partnumber" #: core/docs/drf/viewsets.py:165 msgid "Filter orders with buy_time >= this ISO 8601 datetime" @@ -388,9 +383,9 @@ msgstr "" #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" "Упорядочивайте по одному из следующих признаков: uuid, human_readable_id, " "user_email, user, status, created, modified, buy_time, random. Префикс '-' " @@ -437,7 +432,7 @@ msgstr "" "завершается с использованием баланса пользователя; если используется " "`force_payment`, инициируется транзакция." -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "приобретение заказа без создания учетной записи" @@ -466,8 +461,8 @@ msgid "" "adds a list of products to an order using the provided `product_uuid` and " "`attributes`." msgstr "" -"Добавляет список товаров в заказ, используя предоставленные `product_uuid` и" -" `attributes`." +"Добавляет список товаров в заказ, используя предоставленные `product_uuid` и " +"`attributes`." #: core/docs/drf/viewsets.py:266 msgid "remove product from order" @@ -490,8 +485,8 @@ msgid "" "removes a list of products from an order using the provided `product_uuid` " "and `attributes`" msgstr "" -"Удаляет список товаров из заказа, используя предоставленные `product_uuid` и" -" `attributes`." +"Удаляет список товаров из заказа, используя предоставленные `product_uuid` и " +"`attributes`." #: core/docs/drf/viewsets.py:281 msgid "list all wishlists (simple view)" @@ -572,18 +567,29 @@ msgstr "" msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "Фильтр по одной или нескольким парам имя/значение атрибута. \n" "- **Синтаксис**: `attr_name=method-value[;attr2=method2-value2]...`.\n" -"- **Методы** (по умолчанию используется `icontains`, если опущено): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in`.\n" -"- **Типизация значений**: JSON сначала пытается принять значение (так что вы можете передавать списки/дискреты), `true`/`false` для булевых, целых чисел, плавающих; в противном случае обрабатывается как строка. \n" -"- **Base64**: префикс `b64-` для безопасного для URL base64-кодирования исходного значения. \n" +"- **Методы** (по умолчанию используется `icontains`, если опущено): " +"`iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, " +"`istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, " +"`gt`, `gte`, `in`.\n" +"- **Типизация значений**: JSON сначала пытается принять значение (так что вы " +"можете передавать списки/дискреты), `true`/`false` для булевых, целых чисел, " +"плавающих; в противном случае обрабатывается как строка. \n" +"- **Base64**: префикс `b64-` для безопасного для URL base64-кодирования " +"исходного значения. \n" "Примеры: \n" "`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\", \"bluetooth\"]`,\n" "`b64-description=icontains-aGVhdC1jb2xk`." @@ -638,11 +644,14 @@ msgstr "(точно) Цифровые и физические" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" -"Список полей для сортировки, разделенных запятыми. Для сортировки по убыванию используйте префикс `-`. \n" -"**Разрешенные:** uuid, рейтинг, название, slug, created, modified, price, random" +"Список полей для сортировки, разделенных запятыми. Для сортировки по " +"убыванию используйте префикс `-`. \n" +"**Разрешенные:** uuid, рейтинг, название, slug, created, modified, price, " +"random" #: core/docs/drf/viewsets.py:441 msgid "retrieve a single product (detailed view)" @@ -770,7 +779,7 @@ msgstr "удалить отношение \"заказ-продукт" msgid "add or remove feedback on an order–product relation" msgstr "добавлять или удалять отзывы о связи заказ-продукт" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "Поисковый запрос не предоставлен." @@ -818,8 +827,8 @@ msgstr "Атрибуты" msgid "Quantity" msgstr "Количество" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "Слаг" @@ -882,220 +891,243 @@ msgstr "Уровень" msgid "Product UUID" msgstr "UUID продукта" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "Ключ, который нужно найти в тайнике или вложить в него" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "Данные для хранения в кэше" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "Тайм-аут в секундах для занесения данных в кэш" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "Кэшированные данные" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "Camelized JSON-данные из запрашиваемого URL" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "Допускаются только URL-адреса, начинающиеся с http(s)://" -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "Добавить товар в заказ" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "Заказ {order_uuid} не найден" +msgstr "Заказ {order_uuid} не найден!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "Удалить продукт из заказа" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "Удалить все товары из заказа" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "Купить заказ" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "" "Пожалуйста, укажите либо order_uuid, либо order_hr_id - взаимоисключающие " "варианты!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "Неправильный тип получен из метода order.buy(): {type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "Выполните действие над списком товаров в заказе" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "Удалить/добавить" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "Действие должно быть либо \"добавить\", либо \"удалить\"!" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "Выполните действие над списком продуктов в списке желаний" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "Пожалуйста, укажите значение `wishlist_uuid`." + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "Список желаний {wishlist_uuid} не найден!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "Добавить товар в заказ" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "Список желаний {wishlist_uuid} не найден" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "Удалить продукт из заказа" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "Удалить продукт из заказа" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "Удалить продукт из заказа" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "Купить заказ" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" msgstr "" "Пожалуйста, отправьте атрибуты в виде строки, отформатированной как " "attr1=value1,attr2=value2" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "Добавить или удалить отзыв для продукта заказа" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "Действие должно быть либо `add`, либо `remove`!" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "Заказ товара {order_product_uuid} не найден!" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "Оригинальная строка адреса, предоставленная пользователем" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} не существует: {uuid}" +msgstr "{name} не существует: {uuid}!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "Предел должен быть от 1 до 10" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - работает как шарм" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "Атрибуты" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "Сгруппированные атрибуты" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "Группы атрибутов" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "Категории" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "Бренды" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "Категории" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "Процент наценки" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "" "Какие атрибуты и значения можно использовать для фильтрации этой категории." -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." +#: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." msgstr "" "Минимальные и максимальные цены на товары в этой категории, если они " "доступны." -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "Теги для этой категории" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "Продукты в этой категории" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "Поставщики" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "Широта (координата Y)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "Долгота (координата X)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "Как" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "" "Значение рейтинга от 1 до 10, включительно, или 0, если он не установлен." -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "Представляет собой отзыв пользователя." -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "Уведомления" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "Если применимо, загрузите url для этого продукта заказа" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "Список товаров, заказанных в этом заказе" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "Адрес для выставления счетов" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" @@ -1103,877 +1135,881 @@ msgstr "" "Адрес доставки для данного заказа, оставьте пустым, если он совпадает с " "адресом выставления счета или не применяется" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "Общая стоимость этого заказа" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "Общее количество продуктов в заказе" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "Все ли товары в заказе представлены в цифровом виде" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "Операции для этого заказа" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "Заказы" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "URL-адрес изображения" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" -msgstr "Изображения продукта" +msgstr "Изображения товара" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "Категория" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "Отзывы" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "Бренд" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "Группы атрибутов" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "Цена" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "Количество" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "Количество отзывов" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" -msgstr "Продукция" +msgstr "Товары" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "Промокоды" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "Продукты в продаже" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" -msgstr "Акции" +msgstr "Промоакции" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "Поставщик" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" -msgstr "Продукт" +msgstr "Товар" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "Продукты из списка желаний" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "Списки желаний" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "Tagged products" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "Теги товара" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "Категории с метками" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "Теги категорий" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "Название проекта" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "Электронная почта компании" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "Название компании" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "Адрес компании" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "Номер телефона компании" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "" "'email from', иногда его нужно использовать вместо значения пользователя " "хоста." -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "Пользователь узла электронной почты" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "Максимальная сумма для оплаты" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "Минимальная сумма для оплаты" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "Аналитические данные" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "Рекламные данные" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "Конфигурация" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "Код языка" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "Название языка" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "Языковой флаг, если он существует :)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "Получите список поддерживаемых языков" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "Результаты поиска товаров" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "Результаты поиска товаров" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "Родитель этой группы" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "Родительская группа атрибутов" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "Имя группы атрибутов" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "Группа атрибутов" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "" -"Хранит учетные данные и конечные точки, необходимые для взаимодействия с API" -" поставщика." +"Хранит учетные данные и конечные точки, необходимые для взаимодействия с API " +"поставщика." -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "Информация об аутентификации" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "Определите наценку для товаров, полученных от этого продавца" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "Процент наценки поставщика" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "Имя этого продавца" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "Название поставщика" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "Внутренний идентификатор тега для тега продукта" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "Название тега" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "Удобное название для метки продукта" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "Отображаемое имя тега" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "Метка продукта" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "тег категории" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "теги категорий" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "Загрузите изображение, представляющее эту категорию" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "Изображение категории" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "Определите процент наценки для товаров в этой категории" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "Родитель данной категории для формирования иерархической структуры" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "Родительская категория" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "Название категории" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "Укажите название этой категории" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "Добавьте подробное описание для этой категории" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "Описание категории" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "теги, которые помогают описать или сгруппировать эту категорию" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "Приоритет" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "Название этой марки" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "Название бренда" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "Загрузите логотип, представляющий этот бренд" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "Маленький образ бренда" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "Загрузите большой логотип, представляющий этот бренд" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "Большой имидж бренда" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "Добавьте подробное описание бренда" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "Описание бренда" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "Дополнительные категории, с которыми ассоциируется этот бренд" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "Категории" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "Категория, к которой относится этот продукт" +#: core/models.py:515 +msgid "the vendor supplying this product stock" +msgstr "Поставщик, поставляющий данный товар на склад" -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "По желанию ассоциируйте этот продукт с брендом" +#: core/models.py:516 +msgid "associated vendor" +msgstr "Ассоциированный поставщик" -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "Теги, которые помогают описать или сгруппировать этот продукт" +#: core/models.py:520 +msgid "final price to the customer after markups" +msgstr "Окончательная цена для покупателя после наценок" -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "Указывает, поставляется ли этот продукт в цифровом виде" +#: core/models.py:521 +msgid "selling price" +msgstr "Цена продажи" -#: core/models.py:351 -msgid "is product digital" -msgstr "Является ли продукт цифровым" +#: core/models.py:526 +msgid "the product associated with this stock entry" +msgstr "Продукт, связанный с этой складской записью" -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "Обеспечьте четкое идентификационное название продукта" - -#: core/models.py:358 -msgid "product name" -msgstr "Название продукта" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "Добавьте подробное описание продукта" - -#: core/models.py:364 -msgid "product description" -msgstr "Описание товара" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "Парт. номер для данного товара" - -#: core/models.py:372 -msgid "part number" -msgstr "Парт. номер" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "Категория этого атрибута" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "Группа этого атрибута" - -#: core/models.py:465 -msgid "string" -msgstr "Строка" - -#: core/models.py:466 -msgid "integer" -msgstr "Целое число" - -#: core/models.py:467 -msgid "float" -msgstr "Поплавок" - -#: core/models.py:468 -msgid "boolean" -msgstr "Булево" - -#: core/models.py:469 -msgid "array" -msgstr "Массив" - -#: core/models.py:470 -msgid "object" -msgstr "Объект" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "Тип значения атрибута" - -#: core/models.py:473 -msgid "value type" -msgstr "Тип значения" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "Имя этого атрибута" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "Имя атрибута" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "Атрибут" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "Атрибут этого значения" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "Конкретный продукт, связанный со значением этого атрибута" - -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 msgid "associated product" msgstr "Сопутствующий товар" -#: core/models.py:512 +#: core/models.py:534 +msgid "the price paid to the vendor for this product" +msgstr "Цена, уплаченная продавцу за этот продукт" + +#: core/models.py:535 +msgid "vendor purchase price" +msgstr "Цена покупки у поставщика" + +#: core/models.py:539 +msgid "available quantity of the product in stock" +msgstr "Доступное количество продукта на складе" + +#: core/models.py:540 +msgid "quantity in stock" +msgstr "Количество на складе" + +#: core/models.py:544 +msgid "vendor-assigned SKU for identifying the product" +msgstr "Присвоенный поставщиком SKU для идентификации продукта" + +#: core/models.py:545 +msgid "vendor sku" +msgstr "SKU поставщика" + +#: core/models.py:551 +msgid "digital file associated with this stock if applicable" +msgstr "Цифровой файл, связанный с этой акцией, если применимо" + +#: core/models.py:552 +msgid "digital file" +msgstr "Цифровой файл" + +#: core/models.py:561 +msgid "stock entries" +msgstr "Наличия" + +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "Категория, к которой относится этот продукт" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "По желанию ассоциируйте этот продукт с брендом" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "Теги, которые помогают описать или сгруппировать этот продукт" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "Указывает, поставляется ли этот продукт в цифровом виде" + +#: core/models.py:626 +msgid "is product digital" +msgstr "Является ли продукт цифровым" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "Обеспечьте четкое идентификационное название продукта" + +#: core/models.py:633 +msgid "product name" +msgstr "Название продукта" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "Добавьте подробное описание продукта" + +#: core/models.py:639 +msgid "product description" +msgstr "Описание товара" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "Парт. номер для данного товара" + +#: core/models.py:647 +msgid "part number" +msgstr "Парт. номер" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "Категория этого атрибута" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "Группа этого атрибута" + +#: core/models.py:767 +msgid "string" +msgstr "Строка" + +#: core/models.py:768 +msgid "integer" +msgstr "Целое число" + +#: core/models.py:769 +msgid "float" +msgstr "Поплавок" + +#: core/models.py:770 +msgid "boolean" +msgstr "Булево" + +#: core/models.py:771 +msgid "array" +msgstr "Массив" + +#: core/models.py:772 +msgid "object" +msgstr "Объект" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "Тип значения атрибута" + +#: core/models.py:775 +msgid "value type" +msgstr "Тип значения" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "Имя этого атрибута" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "Имя атрибута" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "Атрибут" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "Атрибут этого значения" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "Конкретный продукт, связанный со значением этого атрибута" + +#: core/models.py:837 msgid "the specific value for this attribute" msgstr "Конкретное значение для этого атрибута" -#: core/models.py:528 +#: core/models.py:871 msgid "provide alternative text for the image for accessibility" msgstr "" "Предоставьте альтернативный текст для изображения, чтобы обеспечить " "доступность" -#: core/models.py:529 +#: core/models.py:872 msgid "image alt text" msgstr "Альтовый текст изображения" -#: core/models.py:532 +#: core/models.py:875 msgid "upload the image file for this product" msgstr "Загрузите файл изображения для этого продукта" -#: core/models.py:533 core/models.py:558 +#: core/models.py:876 core/models.py:901 msgid "product image" msgstr "Изображение продукта" -#: core/models.py:539 +#: core/models.py:882 msgid "determines the order in which images are displayed" msgstr "Определяет порядок отображения изображений" -#: core/models.py:540 +#: core/models.py:883 msgid "display priority" msgstr "Приоритет отображения" -#: core/models.py:545 +#: core/models.py:888 msgid "the product that this image represents" msgstr "Продукт, который представлен на этом изображении" -#: core/models.py:559 +#: core/models.py:902 msgid "product images" -msgstr "Изображения продуктов" +msgstr "Изображения товаров" -#: core/models.py:567 +#: core/models.py:943 msgid "percentage discount for the selected products" msgstr "Процентная скидка на выбранные продукты" -#: core/models.py:568 +#: core/models.py:944 msgid "discount percentage" msgstr "Процент скидки" -#: core/models.py:573 +#: core/models.py:949 msgid "provide a unique name for this promotion" msgstr "Укажите уникальное имя для этой акции" -#: core/models.py:574 +#: core/models.py:950 msgid "promotion name" msgstr "Название акции" -#: core/models.py:580 +#: core/models.py:956 msgid "promotion description" msgstr "Описание акции" -#: core/models.py:585 +#: core/models.py:961 msgid "select which products are included in this promotion" msgstr "Выберите, какие продукты участвуют в этой акции" -#: core/models.py:586 +#: core/models.py:962 msgid "included products" msgstr "Включенные продукты" -#: core/models.py:590 +#: core/models.py:966 msgid "promotion" msgstr "Продвижение" -#: core/models.py:605 -msgid "the vendor supplying this product stock" -msgstr "Поставщик, поставляющий данный товар на склад" - -#: core/models.py:606 -msgid "associated vendor" -msgstr "Ассоциированный поставщик" - -#: core/models.py:610 -msgid "final price to the customer after markups" -msgstr "Окончательная цена для покупателя после наценок" - -#: core/models.py:611 -msgid "selling price" -msgstr "Цена продажи" - -#: core/models.py:616 -msgid "the product associated with this stock entry" -msgstr "Продукт, связанный с этой складской записью" - -#: core/models.py:624 -msgid "the price paid to the vendor for this product" -msgstr "Цена, уплаченная продавцу за этот продукт" - -#: core/models.py:625 -msgid "vendor purchase price" -msgstr "Цена покупки у поставщика" - -#: core/models.py:629 -msgid "available quantity of the product in stock" -msgstr "Доступное количество продукта на складе" - -#: core/models.py:630 -msgid "quantity in stock" -msgstr "Количество на складе" - -#: core/models.py:634 -msgid "vendor-assigned SKU for identifying the product" -msgstr "Присвоенный поставщиком SKU для идентификации продукта" - -#: core/models.py:635 -msgid "vendor sku" -msgstr "SKU поставщика" - -#: core/models.py:641 -msgid "digital file associated with this stock if applicable" -msgstr "Цифровой файл, связанный с этой акцией, если применимо" - -#: core/models.py:642 -msgid "digital file" -msgstr "Цифровой файл" - -#: core/models.py:651 -msgid "stock entries" -msgstr "Складские состояния" - -#: core/models.py:660 +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "Продукты, которые пользователь отметил как желаемые" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "Пользователь, владеющий этим списком желаний" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "Владелец вишлиста" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "Список желаний" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} не существует: {product_uuid}" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "Документальный фильм" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "Документальные фильмы" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "Неразрешенные" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "Адресная строка для клиента" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "Адресная строка" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "Улица" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "Округ" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "Город" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "Регион" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "Почтовый индекс" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "Страна" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "Геолокационная точка(долгота, широта)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "Полный JSON-ответ от геокодера для этого адреса" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "Сохраненный JSON-ответ от сервиса геокодирования" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "Адрес" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "Адреса" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "Уникальный код, используемый пользователем для получения скидки" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "Идентификатор промо-кода" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "Фиксированная сумма скидки, применяемая, если процент не используется" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "Фиксированная сумма скидки" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "" "Процентная скидка, применяемая, если фиксированная сумма не используется" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "Процентная скидка" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "Временная метка, когда истекает срок действия промокода" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "Время окончания срока действия" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "Время, с которого действует этот промокод" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "Время начала действия" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "" "Временная метка, когда был использован промокод, пустая, если он еще не " "использовался" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "Временная метка использования" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "Пользователь, назначенный на этот промокод, если применимо" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "Назначенный пользователь" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "Промокод" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "Промокоды" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." msgstr "" -"Следует определить только один тип скидки (сумма или процент), но не оба или" -" ни один из них." +"Следует определить только один тип скидки (сумма или процент), но не оба или " +"ни один из них." -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "Промокоды" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "Неверный тип скидки для промокода {self.uuid}" +msgstr "Неверный тип скидки для промокода {self.uuid}!" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "Адрес для выставления счетов, используемый для данного заказа" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "Дополнительный промокод, применяемый к этому заказу" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "Примененный промокод" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "Адрес доставки, используемый для данного заказа" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "Адрес доставки" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "Текущий статус заказа в его жизненном цикле" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "Статус заказа" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "" -"JSON-структура уведомлений для отображения пользователям, в административном" -" интерфейсе используется табличный вид" +"JSON-структура уведомлений для отображения пользователям, в административном " +"интерфейсе используется табличный вид" -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "JSON-представление атрибутов заказа для этого заказа" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "Пользователь, разместивший заказ" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "Пользователь" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "Временная метка, когда заказ был завершен" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "Время покупки" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "Человекочитаемый идентификатор для заказа" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "человекочитаемый идентификатор" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "Заказать" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "Пользователь может одновременно иметь только один отложенный ордер!" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "Вы не можете добавить товары в заказ, который не является отложенным." -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "Вы не можете добавить неактивные товары в заказ" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "Вы не можете добавить больше товаров, чем есть на складе" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" -msgstr "" -"Вы не можете удалить товары из заказа, который не является отложенным." +msgstr "Вы не можете удалить товары из заказа, который не является отложенным." -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "{name} не существует в запросе <{query}>." +msgstr "{name} не существует с запросом <{query}>!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "Промокод не существует" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "" "Вы можете купить физические товары только с указанным адресом доставки!" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "Адрес не существует" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "" "В данный момент вы не можете совершить покупку, пожалуйста, повторите " "попытку через несколько минут." -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "Недопустимое значение силы" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "Вы не можете приобрести пустой заказ!" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "Вы не можете купить заказ без пользователя!" + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "Пользователь без баланса не может покупать с балансом!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "Недостаточно средств для выполнения заказа" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" @@ -1981,118 +2017,120 @@ msgstr "" "Вы не можете купить без регистрации, пожалуйста, предоставьте следующую " "информацию: имя клиента, электронная почта клиента, номер телефона клиента" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" msgstr "" "Неверный способ оплаты: {payment_method} от {available_payment_methods}!" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "Цена, уплаченная клиентом за данный продукт на момент покупки" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "Покупная цена на момент заказа" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" -msgstr "" -"Внутренние комментарии для администраторов об этом заказанном продукте" +msgstr "Внутренние комментарии для администраторов об этом заказанном продукте" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "Внутренние комментарии" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "Уведомления пользователей" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "JSON-представление атрибутов этого элемента" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "Атрибуты заказанного продукта" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "Ссылка на родительский заказ, содержащий данный продукт" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "Родительский приказ" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "Конкретный продукт, связанный с этой линией заказа" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "Количество данного товара в заказе" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "Количество продукта" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "Текущий статус этого продукта в заказе" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "Состояние продуктовой линейки" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "У заказанного продукта должен быть связанный с ним заказ!" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "указано неверное действие для обратной связи: {action}" +msgstr "Для обратной связи указано неверное действие: {action}!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "Вы не можете отозвать заказ, который не был получен" -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "Скачать" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "Скачать" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "Вы не можете загрузить цифровой актив для незавершенного заказа" -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "Комментарии пользователей об их опыте использования продукта" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "Комментарии к отзывам" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "" "Ссылка на конкретный продукт в заказе, о котором идет речь в этом отзыве" -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "Сопутствующий товар для заказа" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "Присвоенный пользователем рейтинг продукта" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "Рейтинг продукции" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "Обратная связь" @@ -2103,13 +2141,13 @@ msgstr "" "чтобы добавить отзыв, необходимо указать комментарий, рейтинг и uuid " "продукта заказа." -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "Ошибка при создании промокода: {e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2118,7 +2156,7 @@ msgid "order confirmation" msgstr "Подтверждение заказа" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2129,27 +2167,28 @@ msgstr "Логотип" #: core/templates/shipped_order_delivered_email.html:100 #, python-format msgid "hello %(order.user.first_name)s," -msgstr "Здравствуйте %(order.user.first_name)s," +msgstr "Привет %(order.user.first_name)s," #: core/templates/digital_order_created_email.html:102 #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" msgstr "" -"Благодарим вас за заказ #%(order.pk)s! Мы рады сообщить Вам, что приняли Ваш" -" заказ в работу. Ниже приведены детали вашего заказа:" +"Благодарим вас за заказ #%(order.pk)s! Мы рады сообщить Вам, что приняли Ваш " +"заказ в работу. Ниже приведены детали вашего заказа:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "Всего" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2169,23 +2208,23 @@ msgstr "" #: core/templates/digital_order_created_email.html:133 #, python-format msgid "best regards,
the %(config.PROJECT_NAME)s team" -msgstr "С наилучшими пожеланиями,
команда %(config.PROJECT_NAME)s" +msgstr "С наилучшими пожеланиями,
команда %(config.PROJECT_NAME)s" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "Все права защищены" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "Заказ доставлен" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," -msgstr "Здравствуйте, %(user_first_name)s," +msgstr "Привет %(user_first_name)s," -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" @@ -2194,7 +2233,7 @@ msgstr "" "Мы успешно обработали ваш заказ №%(order_uuid)s! Ниже приведены детали " "вашего заказа:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2202,12 +2241,12 @@ msgstr "" "дополнительная\n" " информация" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "Значение" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -2216,10 +2255,10 @@ msgstr "" "Если у вас возникнут вопросы, обращайтесь в нашу службу поддержки по адресу " "%(contact_email)s." -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "С наилучшими пожеланиями,
команда %(project_name)s" +msgstr "С наилучшими пожеланиями,
команда %(project_name)s" #: core/templates/json_table_widget.html:5 msgid "key" @@ -2228,7 +2267,8 @@ msgstr "Ключ" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" msgstr "" "Спасибо за ваш заказ! Мы рады подтвердить вашу покупку. Ниже приведены " @@ -2248,7 +2288,7 @@ msgstr "Ваш заказ будет доставлен по следующем #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "С наилучшими пожеланиями,
команда %(config.PROJECT_NAME)s" +msgstr "С наилучшими пожеланиями,
Команда %(config.PROJECT_NAME)s" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2269,27 +2309,17 @@ msgstr "" "Неверное значение тайм-аута, оно должно находиться в диапазоне от 0 до " "216000 секунд" -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model} должна быть моделью" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data} должен быть объектом списка" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" -msgstr "{config.PROJECT_NAME} | Свяжитесь с нами" +msgstr "{config.PROJECT_NAME} | свяжитесь с нами по инициативе" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" msgstr "{config.PROJECT_NAME} | Подтверждение заказа" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" msgstr "{config.PROJECT_NAME} | Заказ доставлен" @@ -2306,22 +2336,21 @@ msgstr "Параметр NOMINATIM_URL должен быть настроен!" #, python-brace-format msgid "image dimensions should not exceed w{max_width} x h{max_height} pixels" msgstr "" -"Размеры изображения не должны превышать w{max_width} x h{max_height} " -"пикселей" +"Размеры изображения не должны превышать w{max_width} x h{max_height} пикселей" #: core/validators.py:22 msgid "invalid phone number format" msgstr "Неверный формат телефонного номера" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "Вы можете загрузить цифровой актив только один раз" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "favicon не найден" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "Ошибка геокодирования: {e}" diff --git a/core/locale/zh_Hans/LC_MESSAGES/django.mo b/core/locale/zh_Hans/LC_MESSAGES/django.mo index e15f5f93..714d4ae4 100644 Binary files a/core/locale/zh_Hans/LC_MESSAGES/django.mo and b/core/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/core/locale/zh_Hans/LC_MESSAGES/django.po b/core/locale/zh_Hans/LC_MESSAGES/django.po index f6ed35e3..0c2ae399 100644 --- a/core/locale/zh_Hans/LC_MESSAGES/django.po +++ b/core/locale/zh_Hans/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:05+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,118 +13,115 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: core/abstract.py:12 +#: core/abstract.py:11 msgid "unique id" msgstr "唯一 ID" -#: core/abstract.py:13 +#: core/abstract.py:12 msgid "unique id is used to surely identify any database object" msgstr "唯一 ID 用于确定识别任何数据库对象" -#: core/abstract.py:20 +#: core/abstract.py:19 msgid "is active" msgstr "处于活动状态" -#: core/abstract.py:22 +#: core/abstract.py:20 msgid "" -"if set to false, this object can't be seen by users without needed " -"permission" +"if set to false, this object can't be seen by users without needed permission" msgstr "如果设置为 false,则没有必要权限的用户无法查看此对象" -#: core/abstract.py:26 core/choices.py:18 +#: core/abstract.py:22 core/choices.py:18 msgid "created" msgstr "创建" -#: core/abstract.py:26 +#: core/abstract.py:22 msgid "when the object first appeared on the database" msgstr "对象首次出现在数据库中的时间" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "modified" msgstr "改装" -#: core/abstract.py:29 +#: core/abstract.py:23 msgid "when the object was last modified" msgstr "对象最后一次编辑的时间" -#: core/admin.py:53 +#: core/admin.py:61 msgid "translations" msgstr "翻译" -#: core/admin.py:58 +#: core/admin.py:65 msgid "general" msgstr "一般情况" -#: core/admin.py:60 +#: core/admin.py:67 msgid "relations" msgstr "关系" -#: core/admin.py:65 core/admin.py:67 +#: core/admin.py:72 core/admin.py:74 msgid "metadata" msgstr "元数据" -#: core/admin.py:74 +#: core/admin.py:81 msgid "timestamps" msgstr "时间戳" -#: core/admin.py:80 core/admin.py:95 +#: core/admin.py:96 #, python-format msgid "activate selected %(verbose_name_plural)s" msgstr "激活选定的 %(verbose_name_plural)s" -#: core/admin.py:83 -#, python-format -msgid "%(verbose_name_plural)s activated successfully!" -msgstr "%(verbose_name_plural)s_激活成功!" +#: core/admin.py:101 +msgid "selected items have been activated." +msgstr "所选项目已激活!" -#: core/admin.py:85 core/admin.py:100 +#: core/admin.py:107 #, python-format msgid "deactivate selected %(verbose_name_plural)s" msgstr "停用选定的 %(verbose_name_plural)s" -#: core/admin.py:88 -#, python-format -msgid "%(verbose_name_plural)s deactivated successfully." -msgstr "成功停用%(verbose_name_plural)s_。" +#: core/admin.py:112 +msgid "selected items have been deactivated." +msgstr "选定项目已停用!" -#: core/admin.py:110 core/graphene/object_types.py:411 -#: core/graphene/object_types.py:418 core/models.py:511 core/models.py:519 +#: core/admin.py:124 core/graphene/object_types.py:421 +#: core/graphene/object_types.py:428 core/models.py:836 core/models.py:844 msgid "attribute value" msgstr "属性值" -#: core/admin.py:111 core/graphene/object_types.py:48 core/models.py:520 +#: core/admin.py:125 core/graphene/object_types.py:50 core/models.py:845 msgid "attribute values" msgstr "属性值" -#: core/admin.py:119 +#: core/admin.py:133 msgid "image" msgstr "图片" -#: core/admin.py:120 core/graphene/object_types.py:364 +#: core/admin.py:134 core/graphene/object_types.py:374 msgid "images" msgstr "图片" -#: core/admin.py:128 core/models.py:650 +#: core/admin.py:142 core/models.py:560 msgid "stock" msgstr "库存" -#: core/admin.py:129 core/graphene/object_types.py:465 +#: core/admin.py:143 core/graphene/object_types.py:475 msgid "stocks" msgstr "股票" -#: core/admin.py:139 core/models.py:1384 +#: core/admin.py:153 core/models.py:1829 msgid "order product" msgstr "订购产品" -#: core/admin.py:140 core/graphene/object_types.py:290 core/models.py:1385 +#: core/admin.py:154 core/graphene/object_types.py:293 core/models.py:1830 msgid "order products" msgstr "订购产品" -#: core/admin.py:158 core/admin.py:159 +#: core/admin.py:167 core/admin.py:168 msgid "children" msgstr "儿童" -#: core/admin.py:454 +#: core/admin.py:501 msgid "Config" msgstr "配置" @@ -176,7 +173,7 @@ msgstr "时刻" msgid "successful" msgstr "成功" -#: core/docs/drf/views.py:17 core/graphene/mutations.py:35 +#: core/docs/drf/views.py:17 core/graphene/mutations.py:36 msgid "cache I/O" msgstr "缓存输入/输出" @@ -200,7 +197,7 @@ msgstr "获取应用程序的可公开参数" msgid "send a message to the support team" msgstr "向支持团队发送信息" -#: core/docs/drf/views.py:59 core/graphene/mutations.py:54 +#: core/docs/drf/views.py:59 core/graphene/mutations.py:55 msgid "request a CORSed URL" msgstr "请求 CORSed URL。只允许使用 https。" @@ -216,7 +213,9 @@ msgstr "以企业身份购买订单" msgid "" "purchase an order as a business, using the provided `products` with " "`product_uuid` and `attributes`." -msgstr "使用提供的带有 `product_uuid` 和 `attributes` 的 `products` 作为企业购买订单。" +msgstr "" +"使用提供的带有 `product_uuid` 和 `attributes` 的 `products` 作为企业购买订" +"单。" #: core/docs/drf/viewsets.py:43 msgid "list all attribute groups (simple view)" @@ -239,8 +238,7 @@ msgid "rewrite an existing attribute group saving non-editables" msgstr "重写保存不可编辑的现有属性组" #: core/docs/drf/viewsets.py:63 -msgid "" -"rewrite some fields of an existing attribute group saving non-editables" +msgid "rewrite some fields of an existing attribute group saving non-editables" msgstr "重写现有属性组的某些字段,保存不可编辑的内容" #: core/docs/drf/viewsets.py:70 @@ -288,8 +286,7 @@ msgid "rewrite an existing attribute value saving non-editables" msgstr "重写现有属性值,保存不可编辑属性" #: core/docs/drf/viewsets.py:117 -msgid "" -"rewrite some fields of an existing attribute value saving non-editables" +msgid "rewrite some fields of an existing attribute value saving non-editables" msgstr "重写现有属性值的某些字段,保存不可编辑的属性值" #: core/docs/drf/viewsets.py:124 @@ -326,11 +323,11 @@ msgstr "对于非工作人员用户,只有他们自己的订单才会被退回 #: core/docs/drf/viewsets.py:158 msgid "" -"Case-insensitive substring search across human_readable_id, " -"order_products.product.name, and order_products.product.partnumber" +"Case-insensitive substring search across human_readable_id, order_products." +"product.name, and order_products.product.partnumber" msgstr "" -"在 human_readable_id、order_products.product.name 和 " -"order_products.product.partnumber 中进行不区分大小写的子串搜索" +"在 human_readable_id、order_products.product.name 和 order_products.product." +"partnumber 中进行不区分大小写的子串搜索" #: core/docs/drf/viewsets.py:165 msgid "Filter orders with buy_time >= this ISO 8601 datetime" @@ -362,11 +359,12 @@ msgstr "按订单状态筛选(不区分大小写的子串匹配)" #: core/docs/drf/viewsets.py:201 msgid "" -"Order by one of: uuid, human_readable_id, user_email, user, status, created," -" modified, buy_time, random. Prefix with '-' for descending (e.g. " -"'-buy_time')." +"Order by one of: uuid, human_readable_id, user_email, user, status, created, " +"modified, buy_time, random. Prefix with '-' for descending (e.g. '-" +"buy_time')." msgstr "" -"按以下一项排序:uuid、human_readable_id、user_email、user、status、created、modified、buy_time、random。前缀\"-\"表示降序(例如\"-buy_time\")。" +"按以下一项排序:uuid、human_readable_id、user_email、user、status、created、" +"modified、buy_time、random。前缀\"-\"表示降序(例如\"-buy_time\")。" #: core/docs/drf/viewsets.py:210 msgid "retrieve a single order (detailed view)" @@ -401,9 +399,11 @@ msgid "" "finalizes the order purchase. if `force_balance` is used, the purchase is " "completed using the user's balance; if `force_payment` is used, a " "transaction is initiated." -msgstr "完成订单购买。如果使用 \"force_balance\",则使用用户的余额完成购买;如果使用 \"force_payment\",则启动交易。" +msgstr "" +"完成订单购买。如果使用 \"force_balance\",则使用用户的余额完成购买;如果使用 " +"\"force_payment\",则启动交易。" -#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:280 +#: core/docs/drf/viewsets.py:245 core/graphene/mutations.py:324 msgid "purchase an order without account creation" msgstr "无需创建账户即可购买订单" @@ -520,17 +520,25 @@ msgstr "使用提供的 `product_uuids` 从愿望清单中删除多个产品" msgid "" "Filter by one or more attribute name/value pairs. \n" "• **Syntax**: `attr_name=method-value[;attr2=method2-value2]…` \n" -"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, `icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, `iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" -"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), `true`/`false` for booleans, integers, floats; otherwise treated as string. \n" +"• **Methods** (defaults to `icontains` if omitted): `iexact`, `exact`, " +"`icontains`, `contains`, `isnull`, `startswith`, `istartswith`, `endswith`, " +"`iendswith`, `regex`, `iregex`, `lt`, `lte`, `gt`, `gte`, `in` \n" +"• **Value typing**: JSON is attempted first (so you can pass lists/dicts), " +"`true`/`false` for booleans, integers, floats; otherwise treated as " +"string. \n" "• **Base64**: prefix with `b64-` to URL-safe base64-encode the raw value. \n" "Examples: \n" -"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\",\"bluetooth\"]`, \n" +"`color=exact-red`, `size=gt-10`, `features=in-[\"wifi\"," +"\"bluetooth\"]`, \n" "`b64-description=icontains-aGVhdC1jb2xk`" msgstr "" "根据一个或多个属性名/值对进行筛选。 \n" "- 语法**:`attr_name=method-value[;attr2=method2-value2]...`\n" -"- 方法**(如果省略,默认为 `icontains`):iexact`、`exact`、`icontains`、`contains`、`isnull`、`startswith`、`istartswith`、`endswith`、`iendswith`、`regex`、`iregex`、`lt`、`lte`、`gt`、`gte`、`in`。\n" -"- 值键入**:首先尝试使用 JSON(因此可以传递列表/字段),布尔、整数、浮点数使用 `true`/`false`,否则视为字符串。 \n" +"- 方法**(如果省略,默认为 `icontains`):iexact`、`exact`、`icontains`、" +"`contains`、`isnull`、`startswith`、`istartswith`、`endswith`、`iendswith`、" +"`regex`、`iregex`、`lt`、`lte`、`gt`、`gte`、`in`。\n" +"- 值键入**:首先尝试使用 JSON(因此可以传递列表/字段),布尔、整数、浮点数使" +"用 `true`/`false`,否则视为字符串。 \n" "- **Base64**:以 `b64-` 作为前缀,对原始值进行 URL 安全的 base64 编码。 \n" "示例 \n" "color=exact-red`、`size=gt-10`、`features=in-[\"wifi\"、\"bluetooth\"]`、\n" @@ -586,7 +594,8 @@ msgstr "(准确)数字与实物" #: core/docs/drf/viewsets.py:427 msgid "" -"Comma-separated list of fields to sort by. Prefix with `-` for descending. \n" +"Comma-separated list of fields to sort by. Prefix with `-` for " +"descending. \n" "**Allowed:** uuid, rating, name, slug, created, modified, price, random" msgstr "" "用逗号分隔的要排序的字段列表。前缀为 `-` 表示降序。 \n" @@ -711,7 +720,7 @@ msgstr "删除订单-产品关系" msgid "add or remove feedback on an order–product relation" msgstr "添加或删除订单与产品关系中的反馈信息" -#: core/elasticsearch/__init__.py:106 +#: core/elasticsearch/__init__.py:101 msgid "no search term provided." msgstr "未提供搜索条件。" @@ -759,8 +768,8 @@ msgstr "属性" msgid "Quantity" msgstr "数量" -#: core/filters.py:73 core/filters.py:355 core/models.py:229 -#: core/models.py:307 core/models.py:388 +#: core/filters.py:73 core/filters.py:355 core/models.py:378 core/models.py:472 +#: core/models.py:663 msgid "Slug" msgstr "蛞蝓" @@ -821,1185 +830,1217 @@ msgstr "级别" msgid "Product UUID" msgstr "产品 UUID" -#: core/graphene/mutations.py:38 +#: core/graphene/mutations.py:39 msgid "key to look for in or set into the cache" msgstr "在缓存中查找或设置的关键字" -#: core/graphene/mutations.py:39 +#: core/graphene/mutations.py:40 msgid "data to store in cache" msgstr "缓存中要存储的数据" -#: core/graphene/mutations.py:42 +#: core/graphene/mutations.py:43 msgid "timeout in seconds to set the data for into the cache" msgstr "将数据设置为缓存的超时(以秒为单位" -#: core/graphene/mutations.py:45 +#: core/graphene/mutations.py:46 msgid "cached data" msgstr "缓存数据" -#: core/graphene/mutations.py:59 +#: core/graphene/mutations.py:60 msgid "camelized JSON data from the requested URL" msgstr "从请求的 URL 中获取驼峰化 JSON 数据" -#: core/graphene/mutations.py:64 core/views.py:196 +#: core/graphene/mutations.py:65 core/views.py:356 msgid "only URLs starting with http(s):// are allowed" msgstr "只允许使用以 http(s):// 开头的 URL" -#: core/graphene/mutations.py:79 +#: core/graphene/mutations.py:80 msgid "add a product to the order" msgstr "在订单中添加产品" -#: core/graphene/mutations.py:100 core/graphene/mutations.py:126 -#: core/graphene/mutations.py:228 core/graphene/mutations.py:275 +#: core/graphene/mutations.py:101 core/graphene/mutations.py:127 +#: core/graphene/mutations.py:232 core/graphene/mutations.py:279 #, python-brace-format msgid "order {order_uuid} not found" -msgstr "未找到订单 {order_uuid}" +msgstr "未找到 {order_uuid} 订单!" -#: core/graphene/mutations.py:105 core/graphene/mutations.py:152 +#: core/graphene/mutations.py:106 core/graphene/mutations.py:153 msgid "remove a product from the order" msgstr "从订单中删除产品" -#: core/graphene/mutations.py:131 +#: core/graphene/mutations.py:132 msgid "remove all products from the order" msgstr "从订单中删除所有产品" -#: core/graphene/mutations.py:174 +#: core/graphene/mutations.py:175 msgid "buy an order" msgstr "购买订单" -#: core/graphene/mutations.py:201 core/graphene/mutations.py:253 +#: core/graphene/mutations.py:204 core/graphene/mutations.py:257 msgid "please provide either order_uuid or order_hr_id - mutually exclusive" msgstr "请提供 order_uuid 或 order_hr_id(互斥)!" -#: core/graphene/mutations.py:225 core/graphene/mutations.py:442 -#: core/graphene/mutations.py:483 core/viewsets.py:341 +#: core/graphene/mutations.py:229 core/graphene/mutations.py:486 +#: core/graphene/mutations.py:527 core/viewsets.py:601 msgid "wrong type came from order.buy() method: {type(instance)!s}" msgstr "order.buy() 方法中的类型有误:{type(instance)!s}" -#: core/graphene/mutations.py:233 +#: core/graphene/mutations.py:237 msgid "perform an action on a list of products in the order" msgstr "对订单中的产品列表执行操作" -#: core/graphene/mutations.py:238 +#: core/graphene/mutations.py:242 msgid "remove/add" msgstr "删除/添加" -#: core/graphene/mutations.py:270 +#: core/graphene/mutations.py:274 core/graphene/mutations.py:314 msgid "action must be either add or remove" msgstr "操作必须是 \"添加 \"或 \"删除\"!" -#: core/graphene/mutations.py:326 +#: core/graphene/mutations.py:284 +msgid "perform an action on a list of products in the wishlist" +msgstr "对愿望清单中的产品列表执行操作" + +#: core/graphene/mutations.py:302 +msgid "please provide wishlist_uuid value" +msgstr "请提供 `wishlist_uuid` 值。" + +#: core/graphene/mutations.py:319 core/graphene/mutations.py:392 +#: core/graphene/mutations.py:419 core/graphene/mutations.py:446 +#: core/graphene/mutations.py:489 +#, python-brace-format +msgid "wishlist {wishlist_uuid} not found" +msgstr "未找到 Wishlist {wishlist_uuid}!" + +#: core/graphene/mutations.py:370 msgid "add a product to the wishlist" msgstr "在订单中添加产品" -#: core/graphene/mutations.py:348 core/graphene/mutations.py:375 -#: core/graphene/mutations.py:402 core/graphene/mutations.py:445 -#, python-brace-format -msgid "wishlist {wishlist_uuid} not found" -msgstr "未找到愿望清单 {wishlist_uuid}" - -#: core/graphene/mutations.py:353 +#: core/graphene/mutations.py:397 msgid "remove a product from the wishlist" msgstr "从订单中删除产品" -#: core/graphene/mutations.py:380 +#: core/graphene/mutations.py:424 msgid "remove all products from the wishlist" msgstr "从订单中删除产品" -#: core/graphene/mutations.py:407 +#: core/graphene/mutations.py:451 msgid "buy all products from the wishlist" msgstr "从订单中删除产品" -#: core/graphene/mutations.py:450 +#: core/graphene/mutations.py:494 msgid "buy a product" msgstr "购买订单" -#: core/graphene/mutations.py:456 +#: core/graphene/mutations.py:500 msgid "" -"please send the attributes as the string formatted like " -"attr1=value1,attr2=value2" +"please send the attributes as the string formatted like attr1=value1," +"attr2=value2" msgstr "请以字符串形式发送属性,格式如 attr1=value1,attr2=value2" -#: core/graphene/mutations.py:546 +#: core/graphene/mutations.py:532 +msgid "add or delete a feedback for orderproduct" +msgstr "添加或删除订单产品的反馈信息" + +#: core/graphene/mutations.py:555 +msgid "action must be either `add` or `remove`" +msgstr "操作必须是 \"添加 \"或 \"删除\"!" + +#: core/graphene/mutations.py:558 +#, python-brace-format +msgid "order product {order_product_uuid} not found" +msgstr "未找到订购产品 {order_product_uuid}!" + +#: core/graphene/mutations.py:621 msgid "original address string provided by the user" msgstr "用户提供的原始地址字符串" -#: core/graphene/mutations.py:580 core/viewsets.py:236 core/viewsets.py:344 +#: core/graphene/mutations.py:655 core/models.py:1020 core/models.py:1033 +#: core/models.py:1476 core/models.py:1505 core/models.py:1530 +#: core/viewsets.py:408 core/viewsets.py:604 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} 不存在:{uuid}不存在" +msgstr "{name} 不存在:{uuid}!" -#: core/graphene/mutations.py:593 +#: core/graphene/mutations.py:668 msgid "limit must be between 1 and 10" msgstr "限值必须在 1 和 10 之间" -#: core/graphene/mutations.py:638 +#: core/graphene/mutations.py:713 msgid "elasticsearch - works like a charm" msgstr "ElasticSearch - 工作起来得心应手" -#: core/graphene/object_types.py:55 core/graphene/object_types.py:273 -#: core/graphene/object_types.py:314 core/models.py:488 core/models.py:935 +#: core/graphene/object_types.py:57 core/graphene/object_types.py:276 +#: core/graphene/object_types.py:317 core/models.py:790 core/models.py:1368 msgid "attributes" msgstr "属性" -#: core/graphene/object_types.py:68 +#: core/graphene/object_types.py:70 msgid "grouped attributes" msgstr "分组属性" -#: core/graphene/object_types.py:75 +#: core/graphene/object_types.py:77 msgid "groups of attributes" msgstr "属性组" -#: core/graphene/object_types.py:89 core/graphene/object_types.py:123 -#: core/graphene/object_types.py:153 core/models.py:257 core/models.py:452 +#: core/graphene/object_types.py:91 core/graphene/object_types.py:125 +#: core/graphene/object_types.py:155 core/models.py:403 core/models.py:754 msgid "categories" msgstr "类别" -#: core/graphene/object_types.py:96 core/models.py:321 +#: core/graphene/object_types.py:98 core/models.py:486 msgid "brands" msgstr "品牌" -#: core/graphene/object_types.py:125 +#: core/graphene/object_types.py:127 msgid "category image url" msgstr "类别" -#: core/graphene/object_types.py:126 core/graphene/object_types.py:221 -#: core/models.py:191 +#: core/graphene/object_types.py:128 core/graphene/object_types.py:223 +#: core/models.py:340 msgid "markup percentage" msgstr "加价百分比" -#: core/graphene/object_types.py:129 +#: core/graphene/object_types.py:131 msgid "which attributes and values can be used for filtering this category." msgstr "哪些属性和值可用于筛选该类别。" -#: core/graphene/object_types.py:133 -msgid "" -"minimum and maximum prices for products in this category, if available." +#: core/graphene/object_types.py:135 +msgid "minimum and maximum prices for products in this category, if available." msgstr "该类别产品的最低和最高价格(如有)。" -#: core/graphene/object_types.py:135 +#: core/graphene/object_types.py:137 msgid "tags for this category" msgstr "此类别的标签" -#: core/graphene/object_types.py:136 +#: core/graphene/object_types.py:138 msgid "products in this category" msgstr "该类别中的产品" -#: core/graphene/object_types.py:228 core/models.py:120 +#: core/graphene/object_types.py:230 core/models.py:173 msgid "vendors" msgstr "供应商" -#: core/graphene/object_types.py:232 +#: core/graphene/object_types.py:234 msgid "Latitude (Y coordinate)" msgstr "纬度(Y 坐标)" -#: core/graphene/object_types.py:233 +#: core/graphene/object_types.py:235 msgid "Longitude (X coordinate)" msgstr "经度(X 坐标)" -#: core/graphene/object_types.py:261 +#: core/graphene/object_types.py:264 msgid "comment" msgstr "如何" -#: core/graphene/object_types.py:262 +#: core/graphene/object_types.py:265 msgid "rating value from 1 to 10, inclusive, or 0 if not set." msgstr "评级值从 1 到 10(包括 10),如果未设置,则为 0。" -#: core/graphene/object_types.py:269 +#: core/graphene/object_types.py:272 msgid "represents feedback from a user." msgstr "代表用户的反馈意见。" -#: core/graphene/object_types.py:274 core/graphene/object_types.py:315 -#: core/models.py:929 +#: core/graphene/object_types.py:277 core/graphene/object_types.py:318 +#: core/models.py:1362 msgid "notifications" msgstr "通知" -#: core/graphene/object_types.py:275 +#: core/graphene/object_types.py:278 msgid "download url for this order product if applicable" msgstr "此订单产品的下载网址(如适用" -#: core/graphene/object_types.py:304 +#: core/graphene/object_types.py:307 msgid "a list of order products in this order" msgstr "该订单中的订单产品列表" -#: core/graphene/object_types.py:306 core/models.py:899 +#: core/graphene/object_types.py:309 core/models.py:1332 msgid "billing address" msgstr "账单地址" -#: core/graphene/object_types.py:309 +#: core/graphene/object_types.py:312 msgid "" "shipping address for this order, leave blank if same as billing address or " "if not applicable" msgstr "此订单的送货地址,如果与账单地址相同或不适用,请留空" -#: core/graphene/object_types.py:311 +#: core/graphene/object_types.py:314 msgid "total price of this order" msgstr "订单总价" -#: core/graphene/object_types.py:312 +#: core/graphene/object_types.py:315 msgid "total quantity of products in order" msgstr "订单中产品的总数量" -#: core/graphene/object_types.py:313 +#: core/graphene/object_types.py:316 msgid "are all products in the order digital" msgstr "订单中的所有产品都是数字产品吗?" -#: core/graphene/object_types.py:333 core/models.py:963 +#: core/graphene/object_types.py:319 +msgid "transactions for this order" +msgstr "此订单的交易" + +#: core/graphene/object_types.py:338 core/models.py:1396 msgid "orders" msgstr "订单" -#: core/graphene/object_types.py:349 +#: core/graphene/object_types.py:359 msgid "image url" msgstr "图片 URL" -#: core/graphene/object_types.py:356 +#: core/graphene/object_types.py:366 msgid "product's images" msgstr "产品图片" -#: core/graphene/object_types.py:363 core/models.py:256 core/models.py:331 +#: core/graphene/object_types.py:373 core/models.py:402 core/models.py:606 msgid "category" msgstr "类别" -#: core/graphene/object_types.py:365 core/models.py:1507 +#: core/graphene/object_types.py:375 core/models.py:1988 msgid "feedbacks" msgstr "反馈意见" -#: core/graphene/object_types.py:366 core/models.py:320 core/models.py:340 +#: core/graphene/object_types.py:376 core/models.py:485 core/models.py:615 msgid "brand" msgstr "品牌" -#: core/graphene/object_types.py:367 core/models.py:86 +#: core/graphene/object_types.py:377 core/models.py:113 msgid "attribute groups" msgstr "属性组" -#: core/graphene/object_types.py:368 +#: core/graphene/object_types.py:378 #: core/templates/digital_order_created_email.html:111 -#: core/templates/digital_order_delivered_email.html:110 +#: core/templates/digital_order_delivered_email.html:109 #: core/templates/shipped_order_created_email.html:109 #: core/templates/shipped_order_delivered_email.html:109 msgid "price" msgstr "价格" -#: core/graphene/object_types.py:369 +#: core/graphene/object_types.py:379 #: core/templates/digital_order_created_email.html:110 -#: core/templates/digital_order_delivered_email.html:109 +#: core/templates/digital_order_delivered_email.html:108 #: core/templates/shipped_order_created_email.html:108 #: core/templates/shipped_order_delivered_email.html:108 msgid "quantity" msgstr "数量" -#: core/graphene/object_types.py:370 +#: core/graphene/object_types.py:380 msgid "number of feedbacks" msgstr "反馈数量" -#: core/graphene/object_types.py:388 core/models.py:393 +#: core/graphene/object_types.py:398 core/models.py:668 msgid "products" msgstr "产品" -#: core/graphene/object_types.py:436 +#: core/graphene/object_types.py:446 msgid "promocodes" msgstr "促销代码" -#: core/graphene/object_types.py:446 +#: core/graphene/object_types.py:456 msgid "products on sale" msgstr "销售产品" -#: core/graphene/object_types.py:453 core/models.py:591 +#: core/graphene/object_types.py:463 core/models.py:967 msgid "promotions" msgstr "促销活动" -#: core/graphene/object_types.py:457 core/models.py:119 +#: core/graphene/object_types.py:467 core/models.py:172 msgid "vendor" msgstr "供应商" -#: core/graphene/object_types.py:458 core/models.py:392 +#: core/graphene/object_types.py:468 core/models.py:667 #: core/templates/digital_order_created_email.html:109 -#: core/templates/digital_order_delivered_email.html:108 +#: core/templates/digital_order_delivered_email.html:107 #: core/templates/shipped_order_created_email.html:107 #: core/templates/shipped_order_delivered_email.html:107 msgid "product" msgstr "产品" -#: core/graphene/object_types.py:469 core/models.py:661 +#: core/graphene/object_types.py:479 core/models.py:992 msgid "wishlisted products" msgstr "心愿单上的产品" -#: core/graphene/object_types.py:475 core/models.py:678 +#: core/graphene/object_types.py:485 core/models.py:1009 msgid "wishlists" msgstr "愿望清单" -#: core/graphene/object_types.py:479 +#: core/graphene/object_types.py:489 msgid "tagged products" msgstr "标签产品" -#: core/graphene/object_types.py:486 core/models.py:148 core/models.py:346 +#: core/graphene/object_types.py:496 core/models.py:217 core/models.py:621 msgid "product tags" msgstr "产品标签" -#: core/graphene/object_types.py:490 +#: core/graphene/object_types.py:500 msgid "tagged categories" msgstr "标签类别" -#: core/graphene/object_types.py:497 +#: core/graphene/object_types.py:507 msgid "categories tags" msgstr "类别标签" -#: core/graphene/object_types.py:501 +#: core/graphene/object_types.py:511 msgid "project name" msgstr "项目名称" -#: core/graphene/object_types.py:502 +#: core/graphene/object_types.py:512 msgid "company email" msgstr "公司电子邮件" -#: core/graphene/object_types.py:503 +#: core/graphene/object_types.py:513 msgid "company name" msgstr "公司名称" -#: core/graphene/object_types.py:504 +#: core/graphene/object_types.py:514 msgid "company address" msgstr "公司地址" -#: core/graphene/object_types.py:505 +#: core/graphene/object_types.py:515 msgid "company phone number" msgstr "公司电话号码" -#: core/graphene/object_types.py:506 +#: core/graphene/object_types.py:516 msgid "email from, sometimes it must be used instead of host user value" msgstr "电子邮件来自\",有时必须使用它来代替主机用户值" -#: core/graphene/object_types.py:507 +#: core/graphene/object_types.py:517 msgid "email host user" msgstr "电子邮件主机用户" -#: core/graphene/object_types.py:508 +#: core/graphene/object_types.py:518 msgid "maximum amount for payment" msgstr "最高付款额" -#: core/graphene/object_types.py:509 +#: core/graphene/object_types.py:519 msgid "minimum amount for payment" msgstr "最低付款额" -#: core/graphene/object_types.py:510 +#: core/graphene/object_types.py:520 msgid "analytics data" msgstr "分析数据" -#: core/graphene/object_types.py:511 +#: core/graphene/object_types.py:521 msgid "advertisement data" msgstr "广告数据" -#: core/graphene/object_types.py:514 +#: core/graphene/object_types.py:524 msgid "company configuration" msgstr "配置" -#: core/graphene/object_types.py:518 +#: core/graphene/object_types.py:528 msgid "language code" msgstr "语言代码" -#: core/graphene/object_types.py:519 +#: core/graphene/object_types.py:529 msgid "language name" msgstr "语言名称" -#: core/graphene/object_types.py:520 +#: core/graphene/object_types.py:530 msgid "language flag, if exists :)" msgstr "语言标志(如果有):)" -#: core/graphene/object_types.py:523 +#: core/graphene/object_types.py:533 msgid "supported languages" msgstr "获取支持的语言列表" -#: core/graphene/object_types.py:554 core/graphene/object_types.py:555 -#: core/graphene/object_types.py:556 +#: core/graphene/object_types.py:564 core/graphene/object_types.py:565 +#: core/graphene/object_types.py:566 msgid "products search results" msgstr "产品搜索结果" -#: core/graphene/object_types.py:557 +#: core/graphene/object_types.py:567 msgid "posts search results" msgstr "产品搜索结果" -#: core/models.py:71 +#: core/models.py:98 msgid "parent of this group" msgstr "本组家长" -#: core/models.py:72 +#: core/models.py:99 msgid "parent attribute group" msgstr "父属性组" -#: core/models.py:76 core/models.py:77 +#: core/models.py:103 core/models.py:104 msgid "attribute group's name" msgstr "属性组名称" -#: core/models.py:85 core/models.py:460 +#: core/models.py:112 core/models.py:762 msgid "attribute group" msgstr "属性组" -#: core/models.py:96 +#: core/models.py:150 msgid "stores credentials and endpoints required for vendor communication" msgstr "存储供应商应用程序接口通信所需的凭证和端点" -#: core/models.py:98 +#: core/models.py:151 msgid "authentication info" msgstr "认证信息" -#: core/models.py:103 +#: core/models.py:156 msgid "define the markup for products retrieved from this vendor" msgstr "定义从该供应商获取的产品的标记" -#: core/models.py:104 +#: core/models.py:157 msgid "vendor markup percentage" msgstr "供应商加价百分比" -#: core/models.py:108 +#: core/models.py:161 msgid "name of this vendor" msgstr "供应商名称" -#: core/models.py:109 +#: core/models.py:162 msgid "vendor name" msgstr "供应商名称" -#: core/models.py:133 core/models.py:158 +#: core/models.py:202 core/models.py:240 msgid "internal tag identifier for the product tag" msgstr "产品标签的内部标签标识符" -#: core/models.py:134 core/models.py:159 +#: core/models.py:203 core/models.py:241 msgid "tag name" msgstr "标签名称" -#: core/models.py:138 core/models.py:163 +#: core/models.py:207 core/models.py:245 msgid "user-friendly name for the product tag" msgstr "方便用户使用的产品标签名称" -#: core/models.py:139 core/models.py:164 +#: core/models.py:208 core/models.py:246 msgid "tag display name" msgstr "标签显示名称" -#: core/models.py:147 +#: core/models.py:216 msgid "product tag" msgstr "产品标签" -#: core/models.py:172 +#: core/models.py:254 msgid "category tag" msgstr "类别标签" -#: core/models.py:173 core/models.py:235 +#: core/models.py:255 core/models.py:384 msgid "category tags" msgstr "类别标签" -#: core/models.py:182 +#: core/models.py:331 msgid "upload an image representing this category" msgstr "上传代表该类别的图片" -#: core/models.py:185 +#: core/models.py:334 msgid "category image" msgstr "类别 图像" -#: core/models.py:190 +#: core/models.py:339 msgid "define a markup percentage for products in this category" msgstr "定义该类别产品的加价百分比" -#: core/models.py:199 +#: core/models.py:348 msgid "parent of this category to form a hierarchical structure" msgstr "该类别的父类别,形成等级结构" -#: core/models.py:200 +#: core/models.py:349 msgid "parent category" msgstr "父类" -#: core/models.py:205 +#: core/models.py:354 msgid "category name" msgstr "类别名称" -#: core/models.py:206 +#: core/models.py:355 msgid "provide a name for this category" msgstr "提供该类别的名称" -#: core/models.py:213 +#: core/models.py:362 msgid "add a detailed description for this category" msgstr "为该类别添加详细说明" -#: core/models.py:214 +#: core/models.py:363 msgid "category description" msgstr "类别说明" -#: core/models.py:234 +#: core/models.py:383 msgid "tags that help describe or group this category" msgstr "有助于描述或归类该类别的标签" -#: core/models.py:241 core/models.py:313 +#: core/models.py:390 core/models.py:478 msgid "priority" msgstr "优先权" -#: core/models.py:266 +#: core/models.py:431 msgid "name of this brand" msgstr "品牌名称" -#: core/models.py:267 +#: core/models.py:432 msgid "brand name" msgstr "品牌名称" -#: core/models.py:274 +#: core/models.py:439 msgid "upload a logo representing this brand" msgstr "上传代表该品牌的徽标" -#: core/models.py:276 +#: core/models.py:441 msgid "brand small image" msgstr "品牌小形象" -#: core/models.py:282 +#: core/models.py:447 msgid "upload a big logo representing this brand" msgstr "上传代表该品牌的大徽标" -#: core/models.py:284 +#: core/models.py:449 msgid "brand big image" msgstr "品牌大形象" -#: core/models.py:289 +#: core/models.py:454 msgid "add a detailed description of the brand" msgstr "添加品牌的详细描述" -#: core/models.py:290 +#: core/models.py:455 msgid "brand description" msgstr "品牌描述" -#: core/models.py:295 +#: core/models.py:460 msgid "optional categories that this brand is associated with" msgstr "与该品牌相关的可选类别" -#: core/models.py:296 +#: core/models.py:461 msgid "associated categories" msgstr "类别" -#: core/models.py:330 -msgid "category this product belongs to" -msgstr "该产品所属类别" - -#: core/models.py:339 -msgid "optionally associate this product with a brand" -msgstr "可选择将该产品与某个品牌联系起来" - -#: core/models.py:345 -msgid "tags that help describe or group this product" -msgstr "有助于描述或归类该产品的标签" - -#: core/models.py:350 -msgid "indicates whether this product is digitally delivered" -msgstr "表示该产品是否以数字方式交付" - -#: core/models.py:351 -msgid "is product digital" -msgstr "产品是否数字化" - -#: core/models.py:357 -msgid "provide a clear identifying name for the product" -msgstr "为产品提供一个明确的标识名称" - -#: core/models.py:358 -msgid "product name" -msgstr "产品名称" - -#: core/models.py:363 core/models.py:579 -msgid "add a detailed description of the product" -msgstr "添加产品的详细描述" - -#: core/models.py:364 -msgid "product description" -msgstr "产品说明" - -#: core/models.py:371 -msgid "part number for this product" -msgstr "该产品的零件编号" - -#: core/models.py:372 -msgid "part number" -msgstr "部件编号" - -#: core/models.py:451 -msgid "category of this attribute" -msgstr "该属性的类别" - -#: core/models.py:459 -msgid "group of this attribute" -msgstr "该属性的组" - -#: core/models.py:465 -msgid "string" -msgstr "字符串" - -#: core/models.py:466 -msgid "integer" -msgstr "整数" - -#: core/models.py:467 -msgid "float" -msgstr "浮动" - -#: core/models.py:468 -msgid "boolean" -msgstr "布尔型" - -#: core/models.py:469 -msgid "array" -msgstr "阵列" - -#: core/models.py:470 -msgid "object" -msgstr "对象" - -#: core/models.py:472 -msgid "type of the attribute's value" -msgstr "属性值的类型" - -#: core/models.py:473 -msgid "value type" -msgstr "价值类型" - -#: core/models.py:478 -msgid "name of this attribute" -msgstr "该属性的名称" - -#: core/models.py:479 -msgid "attribute's name" -msgstr "属性名称" - -#: core/models.py:487 core/models.py:499 -#: core/templates/digital_order_delivered_email.html:135 -msgid "attribute" -msgstr "属性" - -#: core/models.py:498 -msgid "attribute of this value" -msgstr "该值的属性" - -#: core/models.py:506 -msgid "the specific product associated with this attribute's value" -msgstr "与该属性值相关的特定产品" - -#: core/models.py:507 core/models.py:546 core/models.py:617 -#: core/models.py:1361 -msgid "associated product" -msgstr "相关产品" - -#: core/models.py:512 -msgid "the specific value for this attribute" -msgstr "该属性的具体值" - -#: core/models.py:528 -msgid "provide alternative text for the image for accessibility" -msgstr "为图像提供替代文字,以便于访问" - -#: core/models.py:529 -msgid "image alt text" -msgstr "图片 alt 文本" - -#: core/models.py:532 -msgid "upload the image file for this product" -msgstr "上传该产品的图片文件" - -#: core/models.py:533 core/models.py:558 -msgid "product image" -msgstr "产品图片" - -#: core/models.py:539 -msgid "determines the order in which images are displayed" -msgstr "确定图像的显示顺序" - -#: core/models.py:540 -msgid "display priority" -msgstr "显示优先级" - -#: core/models.py:545 -msgid "the product that this image represents" -msgstr "该图片所代表的产品" - -#: core/models.py:559 -msgid "product images" -msgstr "产品图片" - -#: core/models.py:567 -msgid "percentage discount for the selected products" -msgstr "所选产品的折扣百分比" - -#: core/models.py:568 -msgid "discount percentage" -msgstr "折扣百分比" - -#: core/models.py:573 -msgid "provide a unique name for this promotion" -msgstr "为该促销活动提供一个独特的名称" - -#: core/models.py:574 -msgid "promotion name" -msgstr "推广名称" - -#: core/models.py:580 -msgid "promotion description" -msgstr "促销说明" - -#: core/models.py:585 -msgid "select which products are included in this promotion" -msgstr "选择促销活动包括哪些产品" - -#: core/models.py:586 -msgid "included products" -msgstr "包括产品" - -#: core/models.py:590 -msgid "promotion" -msgstr "促销活动" - -#: core/models.py:605 +#: core/models.py:515 msgid "the vendor supplying this product stock" msgstr "提供该产品库存的供应商" -#: core/models.py:606 +#: core/models.py:516 msgid "associated vendor" msgstr "相关供应商" -#: core/models.py:610 +#: core/models.py:520 msgid "final price to the customer after markups" msgstr "加价后给客户的最终价格" -#: core/models.py:611 +#: core/models.py:521 msgid "selling price" msgstr "销售价格" -#: core/models.py:616 +#: core/models.py:526 msgid "the product associated with this stock entry" msgstr "与该库存条目相关的产品" -#: core/models.py:624 +#: core/models.py:527 core/models.py:832 core/models.py:889 core/models.py:1803 +msgid "associated product" +msgstr "相关产品" + +#: core/models.py:534 msgid "the price paid to the vendor for this product" msgstr "为该产品支付给供应商的价格" -#: core/models.py:625 +#: core/models.py:535 msgid "vendor purchase price" msgstr "供应商购买价格" -#: core/models.py:629 +#: core/models.py:539 msgid "available quantity of the product in stock" msgstr "产品的可用库存量" -#: core/models.py:630 +#: core/models.py:540 msgid "quantity in stock" msgstr "库存数量" -#: core/models.py:634 +#: core/models.py:544 msgid "vendor-assigned SKU for identifying the product" msgstr "供应商指定的 SKU,用于识别产品" -#: core/models.py:635 +#: core/models.py:545 msgid "vendor sku" msgstr "供应商 SKU" -#: core/models.py:641 +#: core/models.py:551 msgid "digital file associated with this stock if applicable" msgstr "与该库存相关的数字文件(如适用" -#: core/models.py:642 +#: core/models.py:552 msgid "digital file" msgstr "数字文件" -#: core/models.py:651 +#: core/models.py:561 msgid "stock entries" msgstr "库存条目" -#: core/models.py:660 +#: core/models.py:605 +msgid "category this product belongs to" +msgstr "该产品所属类别" + +#: core/models.py:614 +msgid "optionally associate this product with a brand" +msgstr "可选择将该产品与某个品牌联系起来" + +#: core/models.py:620 +msgid "tags that help describe or group this product" +msgstr "有助于描述或归类该产品的标签" + +#: core/models.py:625 +msgid "indicates whether this product is digitally delivered" +msgstr "表示该产品是否以数字方式交付" + +#: core/models.py:626 +msgid "is product digital" +msgstr "产品是否数字化" + +#: core/models.py:632 +msgid "provide a clear identifying name for the product" +msgstr "为产品提供一个明确的标识名称" + +#: core/models.py:633 +msgid "product name" +msgstr "产品名称" + +#: core/models.py:638 core/models.py:955 +msgid "add a detailed description of the product" +msgstr "添加产品的详细描述" + +#: core/models.py:639 +msgid "product description" +msgstr "产品说明" + +#: core/models.py:646 +msgid "part number for this product" +msgstr "该产品的零件编号" + +#: core/models.py:647 +msgid "part number" +msgstr "部件编号" + +#: core/models.py:753 +msgid "category of this attribute" +msgstr "该属性的类别" + +#: core/models.py:761 +msgid "group of this attribute" +msgstr "该属性的组" + +#: core/models.py:767 +msgid "string" +msgstr "字符串" + +#: core/models.py:768 +msgid "integer" +msgstr "整数" + +#: core/models.py:769 +msgid "float" +msgstr "浮动" + +#: core/models.py:770 +msgid "boolean" +msgstr "布尔型" + +#: core/models.py:771 +msgid "array" +msgstr "阵列" + +#: core/models.py:772 +msgid "object" +msgstr "对象" + +#: core/models.py:774 +msgid "type of the attribute's value" +msgstr "属性值的类型" + +#: core/models.py:775 +msgid "value type" +msgstr "价值类型" + +#: core/models.py:780 +msgid "name of this attribute" +msgstr "该属性的名称" + +#: core/models.py:781 +msgid "attribute's name" +msgstr "属性名称" + +#: core/models.py:789 core/models.py:824 +#: core/templates/digital_order_delivered_email.html:134 +msgid "attribute" +msgstr "属性" + +#: core/models.py:823 +msgid "attribute of this value" +msgstr "该值的属性" + +#: core/models.py:831 +msgid "the specific product associated with this attribute's value" +msgstr "与该属性值相关的特定产品" + +#: core/models.py:837 +msgid "the specific value for this attribute" +msgstr "该属性的具体值" + +#: core/models.py:871 +msgid "provide alternative text for the image for accessibility" +msgstr "为图像提供替代文字,以便于访问" + +#: core/models.py:872 +msgid "image alt text" +msgstr "图片 alt 文本" + +#: core/models.py:875 +msgid "upload the image file for this product" +msgstr "上传该产品的图片文件" + +#: core/models.py:876 core/models.py:901 +msgid "product image" +msgstr "产品图片" + +#: core/models.py:882 +msgid "determines the order in which images are displayed" +msgstr "确定图像的显示顺序" + +#: core/models.py:883 +msgid "display priority" +msgstr "显示优先级" + +#: core/models.py:888 +msgid "the product that this image represents" +msgstr "该图片所代表的产品" + +#: core/models.py:902 +msgid "product images" +msgstr "产品图片" + +#: core/models.py:943 +msgid "percentage discount for the selected products" +msgstr "所选产品的折扣百分比" + +#: core/models.py:944 +msgid "discount percentage" +msgstr "折扣百分比" + +#: core/models.py:949 +msgid "provide a unique name for this promotion" +msgstr "为该促销活动提供一个独特的名称" + +#: core/models.py:950 +msgid "promotion name" +msgstr "推广名称" + +#: core/models.py:956 +msgid "promotion description" +msgstr "促销说明" + +#: core/models.py:961 +msgid "select which products are included in this promotion" +msgstr "选择促销活动包括哪些产品" + +#: core/models.py:962 +msgid "included products" +msgstr "包括产品" + +#: core/models.py:966 +msgid "promotion" +msgstr "促销活动" + +#: core/models.py:991 msgid "products that the user has marked as wanted" msgstr "用户标记为想要的产品" -#: core/models.py:668 +#: core/models.py:999 msgid "user who owns this wishlist" msgstr "拥有此愿望清单的用户" -#: core/models.py:669 +#: core/models.py:1000 msgid "wishlist owner" msgstr "心愿单所有者" -#: core/models.py:677 +#: core/models.py:1008 msgid "wishlist" msgstr "愿望清单" -#: core/models.py:688 core/models.py:700 core/models.py:1049 -#: core/models.py:1079 core/models.py:1109 -#, python-brace-format -msgid "{name} does not exist: {product_uuid}" -msgstr "{name} 不存在:{product_uuid} 不存在" - -#: core/models.py:724 +#: core/models.py:1075 msgid "documentary" msgstr "纪录片" -#: core/models.py:725 +#: core/models.py:1076 msgid "documentaries" msgstr "纪录片" -#: core/models.py:735 +#: core/models.py:1086 msgid "unresolved" msgstr "未解决" -#: core/models.py:744 +#: core/models.py:1132 msgid "address line for the customer" msgstr "客户地址栏" -#: core/models.py:745 +#: core/models.py:1133 msgid "address line" msgstr "地址栏" -#: core/models.py:747 +#: core/models.py:1135 msgid "street" msgstr "街道" -#: core/models.py:748 +#: core/models.py:1136 msgid "district" msgstr "地区" -#: core/models.py:749 +#: core/models.py:1137 msgid "city" msgstr "城市" -#: core/models.py:750 +#: core/models.py:1138 msgid "region" msgstr "地区" -#: core/models.py:751 +#: core/models.py:1139 msgid "postal code" msgstr "邮政编码" -#: core/models.py:752 +#: core/models.py:1140 msgid "country" msgstr "国家" -#: core/models.py:759 +#: core/models.py:1147 msgid "geolocation point: (longitude, latitude)" msgstr "地理位置点(经度、纬度)" -#: core/models.py:762 +#: core/models.py:1150 msgid "full JSON response from geocoder for this address" msgstr "地理编码器对此地址的完整 JSON 响应" -#: core/models.py:767 +#: core/models.py:1155 msgid "stored JSON response from the geocoding service" msgstr "存储的来自地理编码服务的 JSON 响应" -#: core/models.py:775 +#: core/models.py:1163 msgid "address" msgstr "地址" -#: core/models.py:776 +#: core/models.py:1164 msgid "addresses" msgstr "地址" -#: core/models.py:793 +#: core/models.py:1209 msgid "unique code used by a user to redeem a discount" msgstr "用户用于兑换折扣的唯一代码" -#: core/models.py:794 +#: core/models.py:1210 msgid "promo code identifier" msgstr "促销代码标识符" -#: core/models.py:801 +#: core/models.py:1217 msgid "fixed discount amount applied if percent is not used" msgstr "如果不使用百分比,则使用固定折扣额" -#: core/models.py:802 +#: core/models.py:1218 msgid "fixed discount amount" msgstr "固定折扣额" -#: core/models.py:808 +#: core/models.py:1224 msgid "percentage discount applied if fixed amount is not used" msgstr "未使用固定金额时适用的折扣百分比" -#: core/models.py:809 +#: core/models.py:1225 msgid "percentage discount" msgstr "折扣百分比" -#: core/models.py:814 +#: core/models.py:1230 msgid "timestamp when the promocode expires" msgstr "促销代码过期的时间戳" -#: core/models.py:815 +#: core/models.py:1231 msgid "end validity time" msgstr "结束有效时间" -#: core/models.py:820 +#: core/models.py:1236 msgid "timestamp from which this promocode is valid" msgstr "该促销代码有效的时间戳" -#: core/models.py:821 +#: core/models.py:1237 msgid "start validity time" msgstr "开始有效时间" -#: core/models.py:826 +#: core/models.py:1242 msgid "timestamp when the promocode was used, blank if not used yet" msgstr "使用促销代码的时间戳,如果尚未使用,则留空" -#: core/models.py:827 +#: core/models.py:1243 msgid "usage timestamp" msgstr "使用时间戳" -#: core/models.py:832 +#: core/models.py:1248 msgid "user assigned to this promocode if applicable" msgstr "分配给此促销代码的用户(如适用" -#: core/models.py:833 +#: core/models.py:1249 msgid "assigned user" msgstr "指定用户" -#: core/models.py:840 +#: core/models.py:1256 msgid "promo code" msgstr "促销代码" -#: core/models.py:841 +#: core/models.py:1257 msgid "promo codes" msgstr "促销代码" -#: core/models.py:849 +#: core/models.py:1264 msgid "" "only one type of discount should be defined (amount or percent), but not " "both or neither." -msgstr "只能定义一种折扣类型(金额或百分比),而不能同时定义两种类型或两者都不定义。" +msgstr "" +"只能定义一种折扣类型(金额或百分比),而不能同时定义两种类型或两者都不定义。" -#: core/models.py:865 +#: core/models.py:1279 msgid "promocode already used" msgstr "促销代码已被使用" -#: core/models.py:882 +#: core/models.py:1295 #, python-brace-format msgid "invalid discount type for promocode {self.uuid}" -msgstr "促销代码 {self.uuid} 的折扣类型无效" +msgstr "促销代码 {self.uuid} 的折扣类型无效!" -#: core/models.py:898 +#: core/models.py:1331 msgid "the billing address used for this order" msgstr "该订单使用的账单地址" -#: core/models.py:906 +#: core/models.py:1339 msgid "optional promo code applied to this order" msgstr "此订单可选择使用促销代码" -#: core/models.py:907 +#: core/models.py:1340 msgid "applied promo code" msgstr "应用促销代码" -#: core/models.py:915 +#: core/models.py:1348 msgid "the shipping address used for this order" msgstr "该订单使用的送货地址" -#: core/models.py:916 +#: core/models.py:1349 msgid "shipping address" msgstr "送货地址" -#: core/models.py:922 +#: core/models.py:1355 msgid "current status of the order in its lifecycle" msgstr "订单在其生命周期中的当前状态" -#: core/models.py:923 +#: core/models.py:1356 msgid "order status" msgstr "订单状态" -#: core/models.py:928 core/models.py:1338 +#: core/models.py:1361 core/models.py:1780 msgid "json structure of notifications to display to users" msgstr "向用户显示的通知的 JSON 结构,在管理用户界面中使用表格视图" -#: core/models.py:934 +#: core/models.py:1367 msgid "json representation of order attributes for this order" msgstr "该订单属性的 JSON 表示形式" -#: core/models.py:940 +#: core/models.py:1373 msgid "the user who placed the order" msgstr "下订单的用户" -#: core/models.py:941 +#: core/models.py:1374 msgid "user" msgstr "用户" -#: core/models.py:947 +#: core/models.py:1380 msgid "the timestamp when the order was finalized" msgstr "订单确定的时间戳" -#: core/models.py:948 +#: core/models.py:1381 msgid "buy time" msgstr "购买时间" -#: core/models.py:955 +#: core/models.py:1388 msgid "a human-readable identifier for the order" msgstr "订单的人工可读标识符" -#: core/models.py:956 +#: core/models.py:1389 msgid "human readable id" msgstr "人类可读 ID" -#: core/models.py:962 +#: core/models.py:1395 msgid "order" msgstr "订购" -#: core/models.py:977 +#: core/models.py:1410 msgid "a user must have only one pending order at a time" msgstr "用户每次只能有一个挂单!" -#: core/models.py:1013 +#: core/models.py:1444 msgid "you cannot add products to an order that is not a pending one" msgstr "您不能向非待处理订单添加产品" -#: core/models.py:1019 +#: core/models.py:1449 msgid "you cannot add inactive products to order" msgstr "您不能在订单中添加非活动产品" -#: core/models.py:1039 +#: core/models.py:1466 msgid "you cannot add more products than available in stock" msgstr "添加的产品数量不能超过现有库存" -#: core/models.py:1062 core/models.py:1090 core/models.py:1100 +#: core/models.py:1488 core/models.py:1513 core/models.py:1521 msgid "you cannot remove products from an order that is not a pending one" msgstr "您不能从非待处理订单中删除产品" -#: core/models.py:1085 +#: core/models.py:1509 #, python-brace-format msgid "{name} does not exist with query <{query}>" -msgstr "查询 <{query}> 时 {name} 不存在" +msgstr "查询 <{query}> 时,{name} 不存在!" -#: core/models.py:1123 +#: core/models.py:1541 msgid "promocode does not exist" msgstr "促销代码不存在" -#: core/models.py:1134 +#: core/models.py:1547 msgid "you can only buy physical products with shipping address specified" msgstr "您只能购买指定送货地址的实物产品!" -#: core/models.py:1155 +#: core/models.py:1566 msgid "address does not exist" msgstr "地址不存在" -#: core/models.py:1167 core/models.py:1220 +#: core/models.py:1587 core/models.py:1645 msgid "you can not buy at this moment, please try again in a few minutes" msgstr "您现在无法购买,请稍后再试。" -#: core/models.py:1173 +#: core/models.py:1590 msgid "invalid force value" msgstr "力值无效" -#: core/models.py:1178 core/models.py:1224 +#: core/models.py:1596 core/models.py:1648 msgid "you cannot purchase an empty order!" msgstr "您不能购买空单!" -#: core/models.py:1196 +#: core/models.py:1615 +msgid "you cannot buy an order without a user" +msgstr "没有用户就无法购买订单!" + +#: core/models.py:1618 +msgid "a user without a balance cannot buy with balance" +msgstr "没有余额的用户不能使用余额购买!" + +#: core/models.py:1623 msgid "insufficient funds to complete the order" msgstr "资金不足,无法完成订单" -#: core/models.py:1233 +#: core/models.py:1657 msgid "" "you cannot buy without registration, please provide the following " "information: customer name, customer email, customer phone number" msgstr "未经注册不能购买,请提供以下信息:客户姓名、客户电子邮件、客户电话号码" -#: core/models.py:1244 +#: core/models.py:1666 #, python-brace-format msgid "" "invalid payment method: {payment_method} from {available_payment_methods}" msgstr "付款方式无效:来自 {available_payment_methods} 的 {payment_method} !" -#: core/models.py:1326 +#: core/models.py:1768 msgid "the price paid by the customer for this product at purchase time" msgstr "客户购买该产品时支付的价格" -#: core/models.py:1327 +#: core/models.py:1769 msgid "purchase price at order time" msgstr "订购时的购买价格" -#: core/models.py:1332 +#: core/models.py:1774 msgid "internal comments for admins about this ordered product" msgstr "管理员对该订购产品的内部评论" -#: core/models.py:1333 +#: core/models.py:1775 msgid "internal comments" msgstr "内部意见" -#: core/models.py:1339 +#: core/models.py:1781 msgid "user notifications" msgstr "用户通知" -#: core/models.py:1344 +#: core/models.py:1786 msgid "json representation of this item's attributes" msgstr "该项属性的 JSON 表示形式" -#: core/models.py:1345 +#: core/models.py:1787 msgid "ordered product attributes" msgstr "有序的产品属性" -#: core/models.py:1350 +#: core/models.py:1792 msgid "reference to the parent order that contains this product" msgstr "对包含该产品的父订单的引用" -#: core/models.py:1351 +#: core/models.py:1793 msgid "parent order" msgstr "父顺序" -#: core/models.py:1360 +#: core/models.py:1802 msgid "the specific product associated with this order line" msgstr "与该订单项目相关的具体产品" -#: core/models.py:1367 +#: core/models.py:1809 msgid "quantity of this specific product in the order" msgstr "订单中该特定产品的数量" -#: core/models.py:1368 +#: core/models.py:1810 msgid "product quantity" msgstr "产品数量" -#: core/models.py:1375 +#: core/models.py:1817 msgid "current status of this product in the order" msgstr "订单中该产品的当前状态" -#: core/models.py:1376 +#: core/models.py:1818 msgid "product line status" msgstr "产品系列状态" -#: core/models.py:1436 +#: core/models.py:1878 +msgid "order product must have an order" +msgstr "订单产品必须有相关的订单!" + +#: core/models.py:1880 #, python-brace-format msgid "wrong action specified for feedback: {action}" -msgstr "为反馈指定了错误的操作:{action}" +msgstr "为反馈指定了错误的操作:{action}!" -#: core/models.py:1447 +#: core/models.py:1888 msgid "you cannot feedback an order which is not received" msgstr "您不能反馈未收到的订单" -#: core/models.py:1459 +#: core/models.py:1923 msgid "download" msgstr "下载" -#: core/models.py:1460 +#: core/models.py:1924 msgid "downloads" msgstr "下载" -#: core/models.py:1469 +#: core/models.py:1932 msgid "you can not download a digital asset for a non-finished order" msgstr "您无法下载未完成订单的数字资产" -#: core/models.py:1481 +#: core/models.py:1962 msgid "user-provided comments about their experience with the product" msgstr "用户提供的产品使用体验评论" -#: core/models.py:1482 +#: core/models.py:1963 msgid "feedback comments" msgstr "反馈意见" -#: core/models.py:1490 -msgid "" -"references the specific product in an order that this feedback is about" +#: core/models.py:1970 +msgid "references the specific product in an order that this feedback is about" msgstr "引用该反馈意见涉及的订单中的具体产品" -#: core/models.py:1492 +#: core/models.py:1971 msgid "related order product" msgstr "相关订购产品" -#: core/models.py:1497 +#: core/models.py:1976 msgid "user-assigned rating for the product" msgstr "用户对产品的评分" -#: core/models.py:1498 +#: core/models.py:1977 msgid "product rating" msgstr "产品评级" -#: core/models.py:1506 +#: core/models.py:1987 msgid "feedback" msgstr "反馈意见" @@ -2008,13 +2049,13 @@ msgid "" "you must provide a comment, rating, and order product uuid to add feedback." msgstr "您必须提供评论、评级和订单产品 uuid 才能添加反馈。" -#: core/signals.py:62 +#: core/signals.py:63 msgid "error during promocode creation: {e!s}" msgstr "创建促销代码时出错:{e!s}" #: core/templates/digital_order_created_email.html:7 #: core/templates/digital_order_created_email.html:100 -#: core/templates/digital_order_delivered_email.html:7 +#: core/templates/digital_order_delivered_email.html:6 #: core/templates/shipped_order_created_email.html:7 #: core/templates/shipped_order_created_email.html:99 #: core/templates/shipped_order_delivered_email.html:7 @@ -2023,7 +2064,7 @@ msgid "order confirmation" msgstr "订单确认" #: core/templates/digital_order_created_email.html:95 -#: core/templates/digital_order_delivered_email.html:95 +#: core/templates/digital_order_delivered_email.html:94 #: core/templates/shipped_order_created_email.html:94 #: core/templates/shipped_order_delivered_email.html:94 msgid "logo" @@ -2034,25 +2075,28 @@ msgstr "标志" #: core/templates/shipped_order_delivered_email.html:100 #, python-format msgid "hello %(order.user.first_name)s," -msgstr "您好 %(order.user.first_name)s、" +msgstr "你好%(order.user.first_name)s_、" #: core/templates/digital_order_created_email.html:102 #, python-format msgid "" "thank you for your order #%(order.pk)s! we are pleased to inform you that\n" -" we have taken your order into work. below are the details of your\n" +" we have taken your order into work. below are " +"the details of your\n" " order:" -msgstr "感谢您的订单 #%(order.pk)s!我们很高兴地通知您,我们已将您的订单付诸实施。以下是您的订单详情:" +msgstr "" +"感谢您的订单 #%(order.pk)s!我们很高兴地通知您,我们已将您的订单付诸实施。以" +"下是您的订单详情:" #: core/templates/digital_order_created_email.html:112 -#: core/templates/digital_order_delivered_email.html:111 +#: core/templates/digital_order_delivered_email.html:110 #: core/templates/shipped_order_created_email.html:110 #: core/templates/shipped_order_delivered_email.html:110 msgid "total" msgstr "总计" #: core/templates/digital_order_created_email.html:125 -#: core/templates/digital_order_delivered_email.html:158 +#: core/templates/digital_order_delivered_email.html:157 #: core/templates/shipped_order_created_email.html:127 #: core/templates/shipped_order_delivered_email.html:127 msgid "total price" @@ -2065,35 +2109,36 @@ msgstr "总价" msgid "" "if you have any questions, feel free to contact our support at\n" " %(config.EMAIL_HOST_USER)s." -msgstr "如果您有任何问题,请随时通过 %(config.EMAIL_HOST_USER)s 联系我们的支持人员。" +msgstr "" +"如果您有任何问题,请随时通过 %(config.EMAIL_HOST_USER)s 联系我们的支持人员。" #: core/templates/digital_order_created_email.html:133 #, python-format msgid "best regards,
the %(config.PROJECT_NAME)s team" -msgstr "致以最诚挚的问候,
%(config.PROJECT_NAME)s团队" +msgstr "致以最诚挚的问候,
%(config.PROJECT_NAME)s_团队" #: core/templates/digital_order_created_email.html:139 -#: core/templates/digital_order_delivered_email.html:172 +#: core/templates/digital_order_delivered_email.html:171 msgid "all rights reserved" msgstr "保留所有权利" -#: core/templates/digital_order_delivered_email.html:100 +#: core/templates/digital_order_delivered_email.html:99 msgid "order delivered" msgstr "订单已送达" -#: core/templates/digital_order_delivered_email.html:101 +#: core/templates/digital_order_delivered_email.html:100 #, python-format msgid "hello %(user_first_name)s," -msgstr "您好 %(user_first_name)s、" +msgstr "你好%(user_first_name)s_、" -#: core/templates/digital_order_delivered_email.html:102 +#: core/templates/digital_order_delivered_email.html:101 #, python-format msgid "" "we have successfully processed your order №%(order_uuid)s! below are the\n" " details of your order:" -msgstr "我们已成功处理了您的订单 №%(order_uuid)s_!以下是您的订单详情:" +msgstr "我们已成功处理您的订单 №%(order_uuid)s_!以下是您的订单详情:" -#: core/templates/digital_order_delivered_email.html:129 +#: core/templates/digital_order_delivered_email.html:128 msgid "" "additional\n" " information" @@ -2101,22 +2146,22 @@ msgstr "" "其他\n" " 附加信息" -#: core/templates/digital_order_delivered_email.html:138 +#: core/templates/digital_order_delivered_email.html:137 #: core/templates/json_table_widget.html:6 msgid "value" msgstr "价值" -#: core/templates/digital_order_delivered_email.html:164 +#: core/templates/digital_order_delivered_email.html:163 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" " %(contact_email)s." msgstr "如果您有任何问题,请随时拨打 %(contact_email)s 联系我们的支持人员。" -#: core/templates/digital_order_delivered_email.html:166 +#: core/templates/digital_order_delivered_email.html:165 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "致以最诚挚的问候,
%(project_name)s团队" +msgstr "致以最诚挚的问候,
%(project_name)s_团队" #: core/templates/json_table_widget.html:5 msgid "key" @@ -2125,7 +2170,8 @@ msgstr "钥匙" #: core/templates/shipped_order_created_email.html:101 #: core/templates/shipped_order_delivered_email.html:101 msgid "" -"thank you for your order! we are pleased to confirm your purchase. below are\n" +"thank you for your order! we are pleased to confirm your purchase. below " +"are\n" " the details of your order:" msgstr "感谢您的订购!我们很高兴确认您的购买。以下是您的订单详情:" @@ -2143,7 +2189,7 @@ msgstr "您的订单将送至以下地址:" #: core/templates/shipped_order_delivered_email.html:142 #, python-format msgid "best regards,
The %(config.PROJECT_NAME)s team" -msgstr "谨致问候,
%(config.PROJECT_NAME)s团队" +msgstr "致以最诚挚的问候,
%(config.PROJECT_NAME)s_团队" #: core/templates/shipped_order_created_email.html:147 #: core/templates/shipped_order_delivered_email.html:147 @@ -2162,30 +2208,20 @@ msgstr "需要数据和超时" msgid "invalid timeout value, it must be between 0 and 216000 seconds" msgstr "超时值无效,必须介于 0 和 216000 秒之间" -#: core/utils/db.py:14 -#, python-brace-format -msgid "{model} must be model" -msgstr "{model}必须是模型" - -#: core/utils/db.py:16 -#, python-brace-format -msgid "{data} must be list object" -msgstr "{data} 必须是列表对象" - #: core/utils/emailing.py:21 #, python-brace-format msgid "{config.PROJECT_NAME} | contact us initiated" msgstr "{config.PROJECT_NAME}| 联系我们" -#: core/utils/emailing.py:57 +#: core/utils/emailing.py:60 #, python-brace-format msgid "{config.PROJECT_NAME} | order confirmation" -msgstr "{config.PROJECT_NAME} | 订单确认| 订单确认" +msgstr "{config.PROJECT_NAME}| 订单确认" -#: core/utils/emailing.py:89 +#: core/utils/emailing.py:95 #, python-brace-format msgid "{config.PROJECT_NAME} | order delivered" -msgstr "{config.PROJECT_NAME}(项目名称| 已交付订单" +msgstr "{config.PROJECT_NAME} | 订单已送达" #: core/utils/messages.py:3 msgid "you do not have permission to perform this action." @@ -2198,21 +2234,21 @@ msgstr "必须配置 NOMINATIM_URL 参数!" #: core/validators.py:16 #, python-brace-format msgid "image dimensions should not exceed w{max_width} x h{max_height} pixels" -msgstr "图片尺寸不应超过 w{max_width} x h{max_height} 像素" +msgstr "图像尺寸不应超过 w{max_width} x h{max_height} 像素!" #: core/validators.py:22 msgid "invalid phone number format" msgstr "电话号码格式无效" -#: core/views.py:266 +#: core/views.py:475 msgid "you can only download the digital asset once" msgstr "您只能下载一次数字资产" -#: core/views.py:302 +#: core/views.py:528 msgid "favicon not found" msgstr "未找到 favicon" -#: core/viewsets.py:684 +#: core/viewsets.py:1099 #, python-brace-format msgid "Geocoding error: {e}" msgstr "地理编码错误:{e}" diff --git a/core/management/commands/__init__.py b/core/management/commands/__init__.py index e69de29b..524885a7 100644 --- a/core/management/commands/__init__.py +++ b/core/management/commands/__init__.py @@ -0,0 +1,7 @@ +from django.conf import settings + + +class RootDirectory: + def __init__(self): + self.label = "root" + self.path = settings.BASE_DIR / "evibes" diff --git a/core/management/commands/check_translated.py b/core/management/commands/check_translated.py index d32dcc14..b7a4683a 100644 --- a/core/management/commands/check_translated.py +++ b/core/management/commands/check_translated.py @@ -7,6 +7,8 @@ import polib from django.apps import apps from django.core.management.base import BaseCommand, CommandError +from core.management.commands import RootDirectory + # Patterns to identify placeholders PLACEHOLDER_REGEXES = [ re.compile(r"\{[^}]+"), # {name}, {type(instance)!s}, etc. @@ -37,7 +39,7 @@ def load_po_sanitized(path: str) -> polib.POFile: with open(path, encoding="utf-8") as f: text = f.read() except OSError as e: - raise CommandError(f"{path}: cannot read file ({e})") + raise CommandError(f"{path}: cannot read file ({e})") from e # fix fuzzy flags and empty header entries text = re.sub(r"^#,(?!\s)", "#, ", text, flags=re.MULTILINE) parts = text.split("\n\n", 1) @@ -52,7 +54,7 @@ def load_po_sanitized(path: str) -> polib.POFile: tmp.close() return polib.pofile(tmp.name) except Exception as e: - raise CommandError(f"{path}: syntax error after sanitization ({e})") + raise CommandError(f"{path}: syntax error after sanitization ({e})") from e finally: with contextlib.suppress(OSError): os.unlink(tmp.name) @@ -94,7 +96,11 @@ class Command(BaseCommand): apps_to_scan: set[str] = set(options["target_apps"]) root_path: str = options.get("root_path") or "/app/" - for app_conf in apps.get_app_configs(): + configs = list(apps.get_app_configs()) + # noinspection PyTypeChecker + configs.append(RootDirectory()) # type: ignore [arg-type] + + for app_conf in configs: if app_conf.label not in apps_to_scan: continue diff --git a/core/management/commands/deepl_translate.py b/core/management/commands/deepl_translate.py index 765a03a5..70f4c9f1 100644 --- a/core/management/commands/deepl_translate.py +++ b/core/management/commands/deepl_translate.py @@ -7,6 +7,8 @@ import requests from django.apps import apps from django.core.management.base import BaseCommand, CommandError +from core.management.commands import RootDirectory + # Mapping from Django locale codes to DeepL API codes DEEPL_TARGET_LANGUAGES_MAPPING = { "en-gb": "EN-GB", @@ -118,12 +120,18 @@ class Command(BaseCommand): ) def handle(self, *args, **options) -> None: - target_langs: list[str] = options["target_languages"] - target_apps: set[str] = set(options["target_apps"]) + target_langs = options["target_languages"] + target_apps = set(options["target_apps"]) auth_key = os.environ.get("DEEPL_AUTH_KEY") if not auth_key: raise CommandError("DEEPL_AUTH_KEY not set") + # attempt to import readline for interactive fill + try: + import readline + except ImportError: + readline = None # type: ignore [assignment] + for target_lang in target_langs: api_code = DEEPL_TARGET_LANGUAGES_MAPPING.get(target_lang) if not api_code: @@ -135,7 +143,9 @@ class Command(BaseCommand): self.stdout.write(self.style.MIGRATE_HEADING(f"→ Translating into {target_lang}")) - for app_conf in apps.get_app_configs(): + configs = list(apps.get_app_configs()) + [RootDirectory()] + + for app_conf in configs: if app_conf.label not in target_apps: continue @@ -146,7 +156,6 @@ class Command(BaseCommand): self.stdout.write(f"• {app_conf.label}: loading English PO…") en_po = load_po_sanitized(en_path) - if not en_po: raise CommandError(f"Failed to load en_GB PO for {app_conf.label}") @@ -154,11 +163,26 @@ class Command(BaseCommand): if missing: self.stdout.write(self.style.NOTICE(f"⚠️ {len(missing)} missing in en_GB")) for e in missing: - input_msgstr = input(f"Enter translation for '{e.msgid}': ").strip() - if input_msgstr: - e.msgstr = input_msgstr + default = e.msgid + if readline: + + def hook(): + readline.insert_text(default) # noqa: B023 + readline.redisplay() + + readline.set_pre_input_hook(hook) # type: ignore [attr-defined] + + prompt = f"Enter translation for '{e.msgid}': " + user_in = input(prompt).strip() + + if readline: + readline.set_pre_input_hook(None) # type: ignore [attr-defined] + + if user_in: + e.msgstr = user_in else: e.msgstr = e.msgid + en_po.save(en_path) self.stdout.write(self.style.SUCCESS("Updated en_GB PO")) @@ -172,13 +196,13 @@ class Command(BaseCommand): "LC_MESSAGES", ) os.makedirs(tgt_dir, exist_ok=True) - tgt_path = os.path.join(tgt_dir, "django.po") + tgt_path = os.path.join(str(tgt_dir), "django.po") old_tgt = None if os.path.exists(tgt_path): self.stdout.write(f" loading existing {target_lang} PO…") try: - old_tgt = load_po_sanitized(tgt_path) + old_tgt = load_po_sanitized(str(tgt_path)) except Exception as e: self.stdout.write(self.style.WARNING(f"Existing PO parse error({e!s}), starting fresh")) @@ -207,8 +231,8 @@ class Command(BaseCommand): protected = [] maps: list[list[str]] = [] - for e in to_trans: - txt = source_map[e.msgid] + for entry in to_trans: + txt = source_map[entry.msgid] p_txt, p_map = placeholderize(txt) protected.append(p_txt) maps.append(p_map) @@ -222,16 +246,16 @@ class Command(BaseCommand): resp.raise_for_status() result = resp.json() except Exception as exc: - raise CommandError(f"DeepL error: {exc} – {resp.text}") + raise CommandError(f"DeepL error: {exc} – {resp.text}") from exc trans = result.get("translations", []) if len(trans) != len(to_trans): raise CommandError(f"Got {len(trans)} translations, expected {len(to_trans)}") - for e, obj, pmap in zip(to_trans, trans, maps, strict=True): - e.msgstr = deplaceholderize(obj["text"], pmap) + for entry, obj, pmap in zip(to_trans, trans, maps, strict=True): + entry.msgstr = deplaceholderize(obj["text"], pmap) - new_po.save(tgt_path) + new_po.save(str(tgt_path)) self.stdout.write(self.style.SUCCESS(f"Saved {tgt_path}")) self.stdout.write(self.style.SUCCESS("Done.")) diff --git a/core/management/commands/delete_never_ordered_products.py b/core/management/commands/delete_never_ordered_products.py new file mode 100644 index 00000000..ce15bf30 --- /dev/null +++ b/core/management/commands/delete_never_ordered_products.py @@ -0,0 +1,33 @@ +from django.core.management.base import BaseCommand + +from core.models import AttributeValue, Product, ProductImage + + +class Command(BaseCommand): + help = "Delete Product rows with no OrderProduct, in batches" + + def add_arguments(self, parser): + parser.add_argument( + "-s", + "--size", + required=False, + default=5000, + help="Chunk size to delete", + ) + + def handle(self, *args, **options): + size = options["size"] + while True: + batch_ids = list(Product.objects.filter(orderproduct__isnull=True).values_list("pk", flat=True)[:size]) + if not batch_ids: + break + try: + AttributeValue.objects.filter(product_id__in=batch_ids).delete() + ProductImage.objects.filter(product_id__in=batch_ids).delete() + Product.objects.filter(pk__in=batch_ids).delete() + except Exception as e: + self.stdout.write("Couldn't delete some of the products(will retry later): %s" % str(e)) + continue + self.stdout.write(f"Deleted {len(batch_ids)} products…") + + self.stdout.write("✅ All unordered products removed.") diff --git a/core/management/commands/delete_products_by_description.py b/core/management/commands/delete_products_by_description.py new file mode 100644 index 00000000..ffa66f54 --- /dev/null +++ b/core/management/commands/delete_products_by_description.py @@ -0,0 +1,35 @@ +from django.core.management.base import BaseCommand + +from core.models import AttributeValue, Product, ProductImage + + +class Command(BaseCommand): + help = "Delete Product rows with special description, in batches" + + def add_arguments(self, parser): + parser.add_argument( + "-s", + "--size", + required=False, + default=5000, + help="Chunk size to delete", + ) + + def handle(self, *args, **options): + size = options["size"] + while True: + batch_ids = list( + Product.objects.filter(description__iexact="EVIBES_DELETED_PRODUCT").values_list("pk", flat=True)[:size] + ) + if not batch_ids: + break + try: + AttributeValue.objects.filter(product_id__in=batch_ids).delete() + ProductImage.objects.filter(product_id__in=batch_ids).delete() + Product.objects.filter(pk__in=batch_ids).delete() + except Exception as e: + self.stdout.write("Couldn't delete some of the products(will retry later): %s" % str(e)) + continue + self.stdout.write(f"Deleted {len(batch_ids)} products…") + + self.stdout.write("✅ All unordered products removed.") diff --git a/core/management/commands/fix_fuzzy.py b/core/management/commands/fix_fuzzy.py index ce047e32..f0d5af60 100644 --- a/core/management/commands/fix_fuzzy.py +++ b/core/management/commands/fix_fuzzy.py @@ -52,12 +52,22 @@ class Command(BaseCommand): new_lines.append("\n") continue - fuzzy_idx = next((i for i, line in enumerate(ent) if line.startswith("#,") and "fuzzy" in line), None) + if any( + line.startswith("#~") or (line.startswith("#,") and line.lstrip("#, ").startswith("msgid ")) + for line in ent + ): + changed = True + continue + + fuzzy_idx = next( + (i for i, line in enumerate(ent) if line.startswith("#,") and "fuzzy" in line), + None, + ) + if fuzzy_idx is not None: - flag_line = ent[fuzzy_idx] - remaining = [f.strip() for f in flag_line[2:].split(",") if f.strip() != "fuzzy"] - if remaining: - ent[fuzzy_idx] = "#, " + ", ".join(remaining) + "\n" + flags = [f.strip() for f in ent[fuzzy_idx][2:].split(",") if f.strip() != "fuzzy"] + if flags: + ent[fuzzy_idx] = "#, " + ", ".join(flags) + "\n" else: del ent[fuzzy_idx] @@ -75,4 +85,4 @@ class Command(BaseCommand): f.writelines(new_lines) self.stdout.write(self.style.SUCCESS(f" → Updated {filepath}")) else: - self.stdout.write(" (no fuzzy entries found)") + self.stdout.write(" (no changes)") diff --git a/core/management/commands/fix_prices.py b/core/management/commands/fix_prices.py index 2a27fd72..6a077690 100644 --- a/core/management/commands/fix_prices.py +++ b/core/management/commands/fix_prices.py @@ -5,7 +5,7 @@ from django.core.management.base import BaseCommand from core.models import Product from core.vendors import AbstractVendor -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") class Command(BaseCommand): @@ -15,7 +15,7 @@ class Command(BaseCommand): for product in Product.objects.filter(stocks__isnull=False): for stock in product.stocks.all(): try: - stock.price = AbstractVendor.round_price_marketologically(stock.price) # type: ignore + stock.price = AbstractVendor.round_price_marketologically(stock.price) stock.save() except Exception as e: self.stdout.write(self.style.WARNING(f"Couldn't fix price on {stock.uuid}")) diff --git a/core/management/commands/translate_fields.py b/core/management/commands/translate_fields.py index d431ec81..53538b4f 100644 --- a/core/management/commands/translate_fields.py +++ b/core/management/commands/translate_fields.py @@ -61,16 +61,16 @@ class Command(BaseCommand): try: module_path, model_name, field_name = target.rsplit(".", 2) - except ValueError: + except ValueError as e: raise CommandError( "Invalid target format. Use app.module.Model.field, e.g. core.models.Product.description" - ) + ) from e try: module = importlib.import_module(module_path) model = getattr(module, model_name) except (ImportError, AttributeError) as e: - raise CommandError(f"Could not import model '{model_name}' from '{module_path}': {e}") + raise CommandError(f"Could not import model '{model_name}' from '{module_path}': {e}") from e dest_suffix = lang.replace("-", "_") dest_field = f"{field_name}_{dest_suffix}" diff --git a/core/managers.py b/core/managers.py index e1978732..3ee4b579 100644 --- a/core/managers.py +++ b/core/managers.py @@ -5,24 +5,24 @@ from constance import config from django.contrib.gis.geos import Point from django.db import models -logger = logging.getLogger("django.request") +logger = logging.getLogger("django") class AddressManager(models.Manager): - def create(self, raw_data: str, **kwargs): # type: ignore - if not raw_data: + def create(self, **kwargs): + if not kwargs.get("raw_data"): raise ValueError("'raw_data' (address string) must be provided.") - params: dict[str, str | int] = { + params: dict[str, str | int] = { # type: ignore [annotation-unchecked] "format": "json", "addressdetails": 1, - "q": raw_data, + "q": kwargs.get("raw_data"), } resp = requests.get(config.NOMINATIM_URL.rstrip("/") + "/search", params=params) resp.raise_for_status() results = resp.json() if not results: - raise ValueError(f"No geocoding result for address: {raw_data}") + raise ValueError(f"No geocoding result for address: {kwargs.get('raw_data')}") data = results[0] addr = data.get("address", {}) @@ -51,7 +51,7 @@ class AddressManager(models.Manager): address_line_2 = "" return super().get_or_create( - raw_data=raw_data, + raw_data=kwargs.get("raw_data"), address_line=f"{address_line_1}, {address_line_2}", street=street, district=district, diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py index 657d41f1..ddfced4c 100644 --- a/core/migrations/0001_initial.py +++ b/core/migrations/0001_initial.py @@ -17,980 +17,2693 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Feedback', + name="Feedback", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('comment', models.TextField(blank=True, - help_text='user-provided comments about their experience with the product', - null=True, verbose_name='feedback comments')), - ('rating', models.FloatField(blank=True, help_text='user-assigned rating for the product', null=True, - validators=[django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(10)], - verbose_name='product rating')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "comment", + models.TextField( + blank=True, + help_text="user-provided comments about their experience with the product", + null=True, + verbose_name="feedback comments", + ), + ), + ( + "rating", + models.FloatField( + blank=True, + help_text="user-assigned rating for the product", + null=True, + validators=[ + django.core.validators.MinValueValidator(0), + django.core.validators.MaxValueValidator(10), + ], + verbose_name="product rating", + ), + ), ], options={ - 'verbose_name': 'feedback', - 'verbose_name_plural': 'feedbacks', + "verbose_name": "feedback", + "verbose_name_plural": "feedbacks", }, ), migrations.CreateModel( - name='OrderProduct', + name="OrderProduct", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('buy_price', models.FloatField(blank=True, - help_text='the price paid by the customer for this product at purchase time', - null=True, verbose_name='purchase price at order time')), - ('comments', - models.TextField(blank=True, help_text='internal comments for admins about this ordered product', - null=True, verbose_name='internal comments')), - ('notifications', - models.JSONField(blank=True, help_text='json structure of notifications to display to users', - null=True, verbose_name='user notifications')), - ('attributes', - models.JSONField(blank=True, help_text="json representation of this item's attributes", null=True, - verbose_name='ordered product attributes')), - ('quantity', - models.PositiveIntegerField(default=1, help_text='quantity of this specific product in the order', - verbose_name='product quantity')), - ('status', models.CharField( - choices=[('FINISHED', 'finished'), ('DELIVERING', 'delivering'), ('DELIVERED', 'delivered'), - ('CANCELED', 'canceled'), ('FAILED', 'failed'), ('PENDING', 'pending'), - ('ACCEPTED', 'accepted'), ('RETURNED', 'money returned')], default='PENDING', - help_text='current status of this product in the order', max_length=128, - verbose_name='product line status')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "buy_price", + models.FloatField( + blank=True, + help_text="the price paid by the customer for this product at purchase time", + null=True, + verbose_name="purchase price at order time", + ), + ), + ( + "comments", + models.TextField( + blank=True, + help_text="internal comments for admins about this ordered product", + null=True, + verbose_name="internal comments", + ), + ), + ( + "notifications", + models.JSONField( + blank=True, + help_text="json structure of notifications to display to users", + null=True, + verbose_name="user notifications", + ), + ), + ( + "attributes", + models.JSONField( + blank=True, + help_text="json representation of this item's attributes", + null=True, + verbose_name="ordered product attributes", + ), + ), + ( + "quantity", + models.PositiveIntegerField( + default=1, + help_text="quantity of this specific product in the order", + verbose_name="product quantity", + ), + ), + ( + "status", + models.CharField( + choices=[ + ("FINISHED", "finished"), + ("DELIVERING", "delivering"), + ("DELIVERED", "delivered"), + ("CANCELED", "canceled"), + ("FAILED", "failed"), + ("PENDING", "pending"), + ("ACCEPTED", "accepted"), + ("RETURNED", "money returned"), + ], + default="PENDING", + help_text="current status of this product in the order", + max_length=128, + verbose_name="product line status", + ), + ), ], options={ - 'verbose_name': 'order product', - 'verbose_name_plural': 'order products', + "verbose_name": "order product", + "verbose_name_plural": "order products", }, ), migrations.CreateModel( - name='Product', + name="Product", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('is_digital', - models.BooleanField(default=False, help_text='indicates whether this product is digitally delivered', - verbose_name='is product digital')), - ('name', models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - verbose_name='product name')), - ('name_en_GB', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_ar_AR', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_cs_CZ', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_da_DK', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_de_DE', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_en_US', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_es_ES', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_fr_FR', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_hi_IN', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_it_IT', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_ja_JP', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_kk_KZ', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_nl_NL', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_pl_PL', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_pt_BR', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_ro_RO', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_ru_RU', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('name_zh_hans', - models.CharField(help_text='provide a clear identifying name for the product', max_length=255, - null=True, verbose_name='product name')), - ('description', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_en_GB', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_ar_AR', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_cs_CZ', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_da_DK', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_de_DE', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_en_US', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_es_ES', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_fr_FR', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_hi_IN', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_it_IT', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_ja_JP', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_kk_KZ', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_nl_NL', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_pl_PL', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_pt_BR', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_ro_RO', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_ru_RU', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), - ('description_zh_hans', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='product description')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "is_digital", + models.BooleanField( + default=False, + help_text="indicates whether this product is digitally delivered", + verbose_name="is product digital", + ), + ), + ( + "name", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + verbose_name="product name", + ), + ), + ( + "name_en_GB", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_ar_AR", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_cs_CZ", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_da_DK", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_de_DE", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_en_US", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_es_ES", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_fr_FR", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_hi_IN", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_it_IT", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_ja_JP", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_kk_KZ", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_nl_NL", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_pl_PL", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_pt_BR", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_ro_RO", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_ru_RU", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "name_zh_hans", + models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), + ), + ( + "description", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_en_GB", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_ar_AR", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_cs_CZ", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_da_DK", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_de_DE", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_en_US", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_es_ES", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_fr_FR", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_hi_IN", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_it_IT", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_ja_JP", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_kk_KZ", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_nl_NL", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_pl_PL", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_pt_BR", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_ro_RO", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_ru_RU", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), + ( + "description_zh_hans", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="product description", + ), + ), ], options={ - 'verbose_name': 'product', - 'verbose_name_plural': 'products', + "verbose_name": "product", + "verbose_name_plural": "products", }, ), migrations.CreateModel( - name='ProductImage', + name="ProductImage", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('alt', - models.CharField(help_text='provide alternative text for the image for accessibility', max_length=255, - verbose_name='image alt text')), - ('image', models.ImageField(help_text='upload the image file for this product', - upload_to=core.utils.get_product_uuid_as_path, - verbose_name='product image')), - ('priority', - models.IntegerField(default=1, help_text='determines the order in which images are displayed', - validators=[django.core.validators.MinValueValidator(1)], - verbose_name='display priority')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "alt", + models.CharField( + help_text="provide alternative text for the image for accessibility", + max_length=255, + verbose_name="image alt text", + ), + ), + ( + "image", + models.ImageField( + help_text="upload the image file for this product", + upload_to=core.utils.get_product_uuid_as_path, + verbose_name="product image", + ), + ), + ( + "priority", + models.IntegerField( + default=1, + help_text="determines the order in which images are displayed", + validators=[django.core.validators.MinValueValidator(1)], + verbose_name="display priority", + ), + ), ], options={ - 'verbose_name': 'product image', - 'verbose_name_plural': 'product images', - 'ordering': ('priority',), + "verbose_name": "product image", + "verbose_name_plural": "product images", + "ordering": ("priority",), }, ), migrations.CreateModel( - name='ProductTag', + name="ProductTag", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('tag_name', models.CharField(help_text='internal tag identifier for the product tag', max_length=255, - verbose_name='tag name')), - ('name', models.CharField(help_text='user-friendly name for the product tag', max_length=255, - verbose_name='tag display name')), - ('name_en_GB', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_ar_AR', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_cs_CZ', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_da_DK', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_de_DE', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_en_US', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_es_ES', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_fr_FR', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_hi_IN', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_it_IT', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_ja_JP', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_kk_KZ', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_nl_NL', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_pl_PL', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_pt_BR', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_ro_RO', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_ru_RU', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), - ('name_zh_hans', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - verbose_name='tag display name')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "tag_name", + models.CharField( + help_text="internal tag identifier for the product tag", max_length=255, verbose_name="tag name" + ), + ), + ( + "name", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + verbose_name="tag display name", + ), + ), + ( + "name_en_GB", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_ar_AR", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_cs_CZ", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_da_DK", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_de_DE", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_en_US", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_es_ES", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_fr_FR", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_hi_IN", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_it_IT", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_ja_JP", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_kk_KZ", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_nl_NL", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_pl_PL", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_pt_BR", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_ro_RO", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_ru_RU", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), + ( + "name_zh_hans", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + verbose_name="tag display name", + ), + ), ], options={ - 'verbose_name': 'product tag', - 'verbose_name_plural': 'product tags', + "verbose_name": "product tag", + "verbose_name_plural": "product tags", }, ), migrations.CreateModel( - name='PromoCode', + name="PromoCode", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('code', models.CharField(default=core.utils.get_random_code, - help_text='unique code used by a user to redeem a discount', max_length=20, - unique=True, verbose_name='promo code identifier')), - ('discount_amount', models.DecimalField(blank=True, decimal_places=2, - help_text='fixed discount amount applied if percent is not used', - max_digits=10, null=True, - verbose_name='fixed discount amount')), - ('discount_percent', - models.IntegerField(blank=True, help_text='percentage discount applied if fixed amount is not used', - null=True, validators=[django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(100)], - verbose_name='percentage discount')), - ('end_time', - models.DateTimeField(blank=True, help_text='timestamp when the promocode expires', null=True, - verbose_name='end validity time')), - ('start_time', - models.DateTimeField(blank=True, help_text='timestamp from which this promocode is valid', null=True, - verbose_name='start validity time')), - ('used_on', models.DateTimeField(blank=True, - help_text='timestamp when the promocode was used, blank if not used yet', - null=True, verbose_name='usage timestamp')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "code", + models.CharField( + default=core.utils.get_random_code, + help_text="unique code used by a user to redeem a discount", + max_length=20, + unique=True, + verbose_name="promo code identifier", + ), + ), + ( + "discount_amount", + models.DecimalField( + blank=True, + decimal_places=2, + help_text="fixed discount amount applied if percent is not used", + max_digits=10, + null=True, + verbose_name="fixed discount amount", + ), + ), + ( + "discount_percent", + models.IntegerField( + blank=True, + help_text="percentage discount applied if fixed amount is not used", + null=True, + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(100), + ], + verbose_name="percentage discount", + ), + ), + ( + "end_time", + models.DateTimeField( + blank=True, + help_text="timestamp when the promocode expires", + null=True, + verbose_name="end validity time", + ), + ), + ( + "start_time", + models.DateTimeField( + blank=True, + help_text="timestamp from which this promocode is valid", + null=True, + verbose_name="start validity time", + ), + ), + ( + "used_on", + models.DateTimeField( + blank=True, + help_text="timestamp when the promocode was used, blank if not used yet", + null=True, + verbose_name="usage timestamp", + ), + ), ], options={ - 'verbose_name': 'promo code', - 'verbose_name_plural': 'promo codes', + "verbose_name": "promo code", + "verbose_name_plural": "promo codes", }, ), migrations.CreateModel( - name='Promotion', + name="Promotion", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('discount_percent', models.IntegerField(help_text='percentage discount for the selected products', - validators=[django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(100)], - verbose_name='discount percentage')), - ('name', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, unique=True, - verbose_name='promotion name')), - ('name_en_GB', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_ar_AR', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_cs_CZ', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_da_DK', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_de_DE', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_en_US', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_es_ES', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_fr_FR', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_hi_IN', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_it_IT', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_ja_JP', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_kk_KZ', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_nl_NL', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_pl_PL', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_pt_BR', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_ro_RO', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_ru_RU', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('name_zh_hans', - models.CharField(help_text='provide a unique name for this promotion', max_length=256, null=True, - unique=True, verbose_name='promotion name')), - ('description', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_en_GB', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_ar_AR', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_cs_CZ', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_da_DK', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_de_DE', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_en_US', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_es_ES', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_fr_FR', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_hi_IN', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_it_IT', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_ja_JP', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_kk_KZ', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_nl_NL', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_pl_PL', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_pt_BR', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_ro_RO', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_ru_RU', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), - ('description_zh_hans', - models.TextField(blank=True, help_text='add a detailed description of the product', null=True, - verbose_name='promotion description')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "discount_percent", + models.IntegerField( + help_text="percentage discount for the selected products", + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(100), + ], + verbose_name="discount percentage", + ), + ), + ( + "name", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_en_GB", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_ar_AR", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_cs_CZ", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_da_DK", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_de_DE", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_en_US", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_es_ES", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_fr_FR", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_hi_IN", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_it_IT", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_ja_JP", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_kk_KZ", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_nl_NL", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_pl_PL", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_pt_BR", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_ro_RO", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_ru_RU", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "name_zh_hans", + models.CharField( + help_text="provide a unique name for this promotion", + max_length=256, + null=True, + unique=True, + verbose_name="promotion name", + ), + ), + ( + "description", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_en_GB", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_ar_AR", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_cs_CZ", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_da_DK", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_de_DE", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_en_US", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_es_ES", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_fr_FR", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_hi_IN", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_it_IT", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_ja_JP", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_kk_KZ", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_nl_NL", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_pl_PL", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_pt_BR", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_ro_RO", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_ru_RU", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), + ( + "description_zh_hans", + models.TextField( + blank=True, + help_text="add a detailed description of the product", + null=True, + verbose_name="promotion description", + ), + ), ], options={ - 'verbose_name': 'promotion', - 'verbose_name_plural': 'promotions', + "verbose_name": "promotion", + "verbose_name_plural": "promotions", }, ), migrations.CreateModel( - name='Stock', + name="Stock", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('price', models.FloatField(default=0.0, help_text='final price to the customer after markups', - verbose_name='selling price')), - ('purchase_price', - models.FloatField(default=0.0, help_text='the price paid to the vendor for this product', - verbose_name='vendor purchase price')), - ('quantity', models.IntegerField(default=0, help_text='available quantity of the product in stock', - verbose_name='quantity in stock')), - ('sku', models.CharField(help_text='vendor-assigned SKU for identifying the product', max_length=255, - verbose_name='vendor sku')), - ('digital_asset', models.FileField(blank=True, default=None, - help_text='digital file associated with this stock if applicable', - null=True, upload_to='downloadables/', verbose_name='digital file')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "price", + models.FloatField( + default=0.0, help_text="final price to the customer after markups", verbose_name="selling price" + ), + ), + ( + "purchase_price", + models.FloatField( + default=0.0, + help_text="the price paid to the vendor for this product", + verbose_name="vendor purchase price", + ), + ), + ( + "quantity", + models.IntegerField( + default=0, + help_text="available quantity of the product in stock", + verbose_name="quantity in stock", + ), + ), + ( + "sku", + models.CharField( + help_text="vendor-assigned SKU for identifying the product", + max_length=255, + verbose_name="vendor sku", + ), + ), + ( + "digital_asset", + models.FileField( + blank=True, + default=None, + help_text="digital file associated with this stock if applicable", + null=True, + upload_to="downloadables/", + verbose_name="digital file", + ), + ), ], options={ - 'verbose_name': 'stock', - 'verbose_name_plural': 'stock entries', + "verbose_name": "stock", + "verbose_name_plural": "stock entries", }, ), migrations.CreateModel( - name='Vendor', + name="Vendor", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('authentication', models.JSONField(blank=True, - help_text='stores credentials and endpoints required for vendor communication', - null=True, verbose_name='authentication info')), - ('markup_percent', - models.IntegerField(default=0, help_text='define the markup for products retrieved from this vendor', - validators=[django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(100)], - verbose_name='vendor markup percentage')), - ('name', models.CharField(help_text='name of this vendor', max_length=255, verbose_name='vendor name')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "authentication", + models.JSONField( + blank=True, + help_text="stores credentials and endpoints required for vendor communication", + null=True, + verbose_name="authentication info", + ), + ), + ( + "markup_percent", + models.IntegerField( + default=0, + help_text="define the markup for products retrieved from this vendor", + validators=[ + django.core.validators.MinValueValidator(0), + django.core.validators.MaxValueValidator(100), + ], + verbose_name="vendor markup percentage", + ), + ), + ("name", models.CharField(help_text="name of this vendor", max_length=255, verbose_name="vendor name")), ], options={ - 'verbose_name': 'vendor', - 'verbose_name_plural': 'vendors', + "verbose_name": "vendor", + "verbose_name_plural": "vendors", }, ), migrations.CreateModel( - name='Wishlist', + name="Wishlist", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), ], options={ - 'verbose_name': 'wishlist', - 'verbose_name_plural': 'wishlists', + "verbose_name": "wishlist", + "verbose_name_plural": "wishlists", }, ), migrations.CreateModel( - name='AttributeGroup', + name="AttributeGroup", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('name', models.CharField(help_text="attribute group's name", max_length=255, - verbose_name="attribute group's name")), - ('name_en_GB', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_ar_AR', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_cs_CZ', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_da_DK', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_de_DE', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_en_US', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_es_ES', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_fr_FR', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_hi_IN', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_it_IT', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_ja_JP', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_kk_KZ', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_nl_NL', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_pl_PL', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_pt_BR', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_ro_RO', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_ru_RU', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('name_zh_hans', models.CharField(help_text="attribute group's name", max_length=255, null=True, - verbose_name="attribute group's name")), - ('parent', models.ForeignKey(blank=True, help_text='parent of this group', null=True, - on_delete=django.db.models.deletion.CASCADE, related_name='children', - to='core.attributegroup', verbose_name='parent attribute group')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "name", + models.CharField( + help_text="attribute group's name", max_length=255, verbose_name="attribute group's name" + ), + ), + ( + "name_en_GB", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_ar_AR", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_cs_CZ", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_da_DK", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_de_DE", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_en_US", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_es_ES", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_fr_FR", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_hi_IN", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_it_IT", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_ja_JP", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_kk_KZ", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_nl_NL", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_pl_PL", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_pt_BR", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_ro_RO", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_ru_RU", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "name_zh_hans", + models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + verbose_name="attribute group's name", + ), + ), + ( + "parent", + models.ForeignKey( + blank=True, + help_text="parent of this group", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="children", + to="core.attributegroup", + verbose_name="parent attribute group", + ), + ), ], options={ - 'verbose_name': 'attribute group', - 'verbose_name_plural': 'attribute groups', + "verbose_name": "attribute group", + "verbose_name_plural": "attribute groups", }, ), migrations.CreateModel( - name='Attribute', + name="Attribute", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('value_type', models.CharField( - choices=[('string', 'string'), ('integer', 'integer'), ('float', 'float'), ('boolean', 'boolean'), - ('array', 'array'), ('object', 'object')], help_text="type of the attribute's value", - max_length=50, verbose_name='value type')), - ('name', - models.CharField(help_text='name of this attribute', max_length=255, verbose_name="attribute's name")), - ('name_en_GB', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_ar_AR', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_cs_CZ', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_da_DK', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_de_DE', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_en_US', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_es_ES', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_fr_FR', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_hi_IN', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_it_IT', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_ja_JP', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_kk_KZ', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_nl_NL', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_pl_PL', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_pt_BR', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_ro_RO', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_ru_RU', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('name_zh_hans', models.CharField(help_text='name of this attribute', max_length=255, null=True, - verbose_name="attribute's name")), - ('group', - models.ForeignKey(help_text='group of this attribute', on_delete=django.db.models.deletion.CASCADE, - related_name='attributes', to='core.attributegroup', - verbose_name='attribute group')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "value_type", + models.CharField( + choices=[ + ("string", "string"), + ("integer", "integer"), + ("float", "float"), + ("boolean", "boolean"), + ("array", "array"), + ("object", "object"), + ], + help_text="type of the attribute's value", + max_length=50, + verbose_name="value type", + ), + ), + ( + "name", + models.CharField( + help_text="name of this attribute", max_length=255, verbose_name="attribute's name" + ), + ), + ( + "name_en_GB", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_ar_AR", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_cs_CZ", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_da_DK", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_de_DE", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_en_US", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_es_ES", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_fr_FR", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_hi_IN", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_it_IT", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_ja_JP", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_kk_KZ", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_nl_NL", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_pl_PL", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_pt_BR", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_ro_RO", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_ru_RU", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "name_zh_hans", + models.CharField( + help_text="name of this attribute", max_length=255, null=True, verbose_name="attribute's name" + ), + ), + ( + "group", + models.ForeignKey( + help_text="group of this attribute", + on_delete=django.db.models.deletion.CASCADE, + related_name="attributes", + to="core.attributegroup", + verbose_name="attribute group", + ), + ), ], options={ - 'verbose_name': 'attribute', - 'verbose_name_plural': 'attributes', + "verbose_name": "attribute", + "verbose_name_plural": "attributes", }, ), migrations.CreateModel( - name='AttributeValue', + name="AttributeValue", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('value', - models.TextField(help_text='the specific value for this attribute', verbose_name='attribute value')), - ('value_en_GB', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_ar_AR', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_cs_CZ', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_da_DK', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_de_DE', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_en_US', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_es_ES', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_fr_FR', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_hi_IN', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_it_IT', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_ja_JP', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_kk_KZ', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_nl_NL', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_pl_PL', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_pt_BR', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_ro_RO', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_ru_RU', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('value_zh_hans', models.TextField(help_text='the specific value for this attribute', null=True, - verbose_name='attribute value')), - ('attribute', - models.ForeignKey(help_text='attribute of this value', on_delete=django.db.models.deletion.CASCADE, - related_name='values', to='core.attribute', verbose_name='attribute')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "value", + models.TextField(help_text="the specific value for this attribute", verbose_name="attribute value"), + ), + ( + "value_en_GB", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_ar_AR", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_cs_CZ", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_da_DK", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_de_DE", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_en_US", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_es_ES", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_fr_FR", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_hi_IN", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_it_IT", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_ja_JP", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_kk_KZ", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_nl_NL", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_pl_PL", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_pt_BR", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_ro_RO", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_ru_RU", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "value_zh_hans", + models.TextField( + help_text="the specific value for this attribute", null=True, verbose_name="attribute value" + ), + ), + ( + "attribute", + models.ForeignKey( + help_text="attribute of this value", + on_delete=django.db.models.deletion.CASCADE, + related_name="values", + to="core.attribute", + verbose_name="attribute", + ), + ), ], options={ - 'verbose_name': 'attribute value', - 'verbose_name_plural': 'attribute values', + "verbose_name": "attribute value", + "verbose_name_plural": "attribute values", }, ), migrations.CreateModel( - name='Category', + name="Category", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('image', models.ImageField(help_text='upload an image representing this category', null=True, - upload_to='categories/', - validators=[core.validators.validate_category_image_dimensions], - verbose_name='category image')), - ('markup_percent', - models.IntegerField(default=0, help_text='define a markup percentage for products in this category', - validators=[django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(100)], - verbose_name='markup percentage')), - ('name', models.CharField(help_text='provide a name for this category', max_length=255, - verbose_name='category name')), - ('name_en_GB', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_ar_AR', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_cs_CZ', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_da_DK', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_de_DE', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_en_US', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_es_ES', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_fr_FR', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_hi_IN', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_it_IT', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_ja_JP', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_kk_KZ', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_nl_NL', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_pl_PL', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_pt_BR', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_ro_RO', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_ru_RU', models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('name_zh_hans', - models.CharField(help_text='provide a name for this category', max_length=255, null=True, - verbose_name='category name')), - ('description', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_en_GB', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_ar_AR', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_cs_CZ', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_da_DK', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_de_DE', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_en_US', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_es_ES', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_fr_FR', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_hi_IN', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_it_IT', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_ja_JP', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_kk_KZ', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_nl_NL', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_pl_PL', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_pt_BR', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_ro_RO', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_ru_RU', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('description_zh_hans', - models.TextField(blank=True, help_text='add a detailed description for this category', null=True, - verbose_name='category description')), - ('lft', models.PositiveIntegerField(editable=False)), - ('rght', models.PositiveIntegerField(editable=False)), - ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), - ('level', models.PositiveIntegerField(editable=False)), - ('parent', mptt.fields.TreeForeignKey(blank=True, - help_text='parent of this category to form a hierarchical structure', - null=True, on_delete=django.db.models.deletion.CASCADE, - related_name='children', to='core.category', - verbose_name='parent category')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "image", + models.ImageField( + help_text="upload an image representing this category", + null=True, + upload_to="categories/", + validators=[core.validators.validate_category_image_dimensions], + verbose_name="category image", + ), + ), + ( + "markup_percent", + models.IntegerField( + default=0, + help_text="define a markup percentage for products in this category", + validators=[ + django.core.validators.MinValueValidator(0), + django.core.validators.MaxValueValidator(100), + ], + verbose_name="markup percentage", + ), + ), + ( + "name", + models.CharField( + help_text="provide a name for this category", max_length=255, verbose_name="category name" + ), + ), + ( + "name_en_GB", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_ar_AR", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_cs_CZ", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_da_DK", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_de_DE", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_en_US", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_es_ES", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_fr_FR", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_hi_IN", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_it_IT", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_ja_JP", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_kk_KZ", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_nl_NL", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_pl_PL", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_pt_BR", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_ro_RO", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_ru_RU", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "name_zh_hans", + models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + verbose_name="category name", + ), + ), + ( + "description", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_en_GB", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_ar_AR", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_cs_CZ", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_da_DK", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_de_DE", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_en_US", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_es_ES", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_fr_FR", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_hi_IN", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_it_IT", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_ja_JP", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_kk_KZ", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_nl_NL", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_pl_PL", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_pt_BR", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_ro_RO", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_ru_RU", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ( + "description_zh_hans", + models.TextField( + blank=True, + help_text="add a detailed description for this category", + null=True, + verbose_name="category description", + ), + ), + ("lft", models.PositiveIntegerField(editable=False)), + ("rght", models.PositiveIntegerField(editable=False)), + ("tree_id", models.PositiveIntegerField(db_index=True, editable=False)), + ("level", models.PositiveIntegerField(editable=False)), + ( + "parent", + mptt.fields.TreeForeignKey( + blank=True, + help_text="parent of this category to form a hierarchical structure", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="children", + to="core.category", + verbose_name="parent category", + ), + ), ], options={ - 'verbose_name': 'category', - 'verbose_name_plural': 'categories', - 'ordering': ['tree_id', 'lft'], + "verbose_name": "category", + "verbose_name_plural": "categories", + "ordering": ["tree_id", "lft"], }, ), migrations.CreateModel( - name='Brand', + name="Brand", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('name', models.CharField(help_text='name of this brand', max_length=255, verbose_name='brand name')), - ('category', - models.ForeignKey(blank=True, help_text='optional category that this brand is associated with', - null=True, on_delete=django.db.models.deletion.PROTECT, to='core.category', - verbose_name='associated category')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ("name", models.CharField(help_text="name of this brand", max_length=255, verbose_name="brand name")), + ( + "category", + models.ForeignKey( + blank=True, + help_text="optional category that this brand is associated with", + null=True, + on_delete=django.db.models.deletion.PROTECT, + to="core.category", + verbose_name="associated category", + ), + ), ], options={ - 'verbose_name': 'brand', - 'verbose_name_plural': 'brands', + "verbose_name": "brand", + "verbose_name_plural": "brands", }, ), migrations.AddField( - model_name='attribute', - name='categories', - field=models.ManyToManyField(help_text='category of this attribute', related_name='attributes', - to='core.category', verbose_name='categories'), + model_name="attribute", + name="categories", + field=models.ManyToManyField( + help_text="category of this attribute", + related_name="attributes", + to="core.category", + verbose_name="categories", + ), ), migrations.CreateModel( - name='Order', + name="Order", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('status', models.CharField( - choices=[('PENDING', 'pending'), ('FAILED', 'failed'), ('PAYMENT', 'payment'), - ('CREATED', 'created'), ('DELIVERING', 'delivering'), ('FINISHED', 'finished')], - default='PENDING', help_text='current status of the order in its lifecycle', max_length=64, - verbose_name='order status')), - ('notifications', - models.JSONField(blank=True, help_text='json structure of notifications to display to users', - null=True, verbose_name='notifications')), - ('attributes', - models.JSONField(blank=True, help_text='json representation of order attributes for this order', - null=True, verbose_name='attributes')), - ('buy_time', - models.DateTimeField(blank=True, default=None, help_text='the timestamp when the order was finalized', - null=True, verbose_name='buy time')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "status", + models.CharField( + choices=[ + ("PENDING", "pending"), + ("FAILED", "failed"), + ("PAYMENT", "payment"), + ("CREATED", "created"), + ("DELIVERING", "delivering"), + ("FINISHED", "finished"), + ], + default="PENDING", + help_text="current status of the order in its lifecycle", + max_length=64, + verbose_name="order status", + ), + ), + ( + "notifications", + models.JSONField( + blank=True, + help_text="json structure of notifications to display to users", + null=True, + verbose_name="notifications", + ), + ), + ( + "attributes", + models.JSONField( + blank=True, + help_text="json representation of order attributes for this order", + null=True, + verbose_name="attributes", + ), + ), + ( + "buy_time", + models.DateTimeField( + blank=True, + default=None, + help_text="the timestamp when the order was finalized", + null=True, + verbose_name="buy time", + ), + ), ], options={ - 'verbose_name': 'order', - 'verbose_name_plural': 'orders', + "verbose_name": "order", + "verbose_name_plural": "orders", }, ), ] diff --git a/core/migrations/0002_initial.py b/core/migrations/0002_initial.py index af993959..8907808a 100644 --- a/core/migrations/0002_initial.py +++ b/core/migrations/0002_initial.py @@ -7,101 +7,205 @@ from django.db import migrations, models class Migration(migrations.Migration): - initial = True dependencies = [ - ('core', '0001_initial'), + ("core", "0001_initial"), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.AddField( - model_name='order', - name='user', - field=models.ForeignKey(help_text='the user who placed the order', on_delete=django.db.models.deletion.CASCADE, related_name='orders', to=settings.AUTH_USER_MODEL, verbose_name='user'), + model_name="order", + name="user", + field=models.ForeignKey( + help_text="the user who placed the order", + on_delete=django.db.models.deletion.CASCADE, + related_name="orders", + to=settings.AUTH_USER_MODEL, + verbose_name="user", + ), ), migrations.AddField( - model_name='orderproduct', - name='order', - field=models.ForeignKey(help_text='reference to the parent order that contains this product', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='order_products', to='core.order', verbose_name='parent order'), + model_name="orderproduct", + name="order", + field=models.ForeignKey( + help_text="reference to the parent order that contains this product", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="order_products", + to="core.order", + verbose_name="parent order", + ), ), migrations.AddField( - model_name='feedback', - name='order_product', - field=models.OneToOneField(help_text='references the specific product in an order that this feedback is about', on_delete=django.db.models.deletion.CASCADE, to='core.orderproduct', verbose_name='related order product'), + model_name="feedback", + name="order_product", + field=models.OneToOneField( + help_text="references the specific product in an order that this feedback is about", + on_delete=django.db.models.deletion.CASCADE, + to="core.orderproduct", + verbose_name="related order product", + ), ), migrations.AddField( - model_name='product', - name='brand', - field=models.ForeignKey(blank=True, help_text='optionally associate this product with a brand', null=True, on_delete=django.db.models.deletion.CASCADE, to='core.brand', verbose_name='brand'), + model_name="product", + name="brand", + field=models.ForeignKey( + blank=True, + help_text="optionally associate this product with a brand", + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="core.brand", + verbose_name="brand", + ), ), migrations.AddField( - model_name='product', - name='category', - field=models.ForeignKey(help_text='category this product belongs to', on_delete=django.db.models.deletion.CASCADE, to='core.category', verbose_name='category'), + model_name="product", + name="category", + field=models.ForeignKey( + help_text="category this product belongs to", + on_delete=django.db.models.deletion.CASCADE, + to="core.category", + verbose_name="category", + ), ), migrations.AddField( - model_name='orderproduct', - name='product', - field=models.ForeignKey(blank=True, help_text='the specific product associated with this order line', null=True, on_delete=django.db.models.deletion.PROTECT, to='core.product', verbose_name='associated product'), + model_name="orderproduct", + name="product", + field=models.ForeignKey( + blank=True, + help_text="the specific product associated with this order line", + null=True, + on_delete=django.db.models.deletion.PROTECT, + to="core.product", + verbose_name="associated product", + ), ), migrations.AddField( - model_name='attributevalue', - name='product', - field=models.ForeignKey(help_text="the specific product associated with this attribute's value", null=True, on_delete=django.db.models.deletion.CASCADE, related_name='attributes', to='core.product', verbose_name='associated product'), + model_name="attributevalue", + name="product", + field=models.ForeignKey( + help_text="the specific product associated with this attribute's value", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="attributes", + to="core.product", + verbose_name="associated product", + ), ), migrations.AddField( - model_name='productimage', - name='product', - field=models.ForeignKey(help_text='the product that this image represents', on_delete=django.db.models.deletion.CASCADE, related_name='images', to='core.product', verbose_name='associated product'), + model_name="productimage", + name="product", + field=models.ForeignKey( + help_text="the product that this image represents", + on_delete=django.db.models.deletion.CASCADE, + related_name="images", + to="core.product", + verbose_name="associated product", + ), ), migrations.AddField( - model_name='product', - name='tags', - field=models.ManyToManyField(blank=True, help_text='tags that help describe or group this product', to='core.producttag', verbose_name='product tags'), + model_name="product", + name="tags", + field=models.ManyToManyField( + blank=True, + help_text="tags that help describe or group this product", + to="core.producttag", + verbose_name="product tags", + ), ), migrations.AddField( - model_name='promocode', - name='user', - field=models.ForeignKey(blank=True, help_text='user assigned to this promocode if applicable', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='promocodes', to=settings.AUTH_USER_MODEL, verbose_name='assigned user'), + model_name="promocode", + name="user", + field=models.ForeignKey( + blank=True, + help_text="user assigned to this promocode if applicable", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="promocodes", + to=settings.AUTH_USER_MODEL, + verbose_name="assigned user", + ), ), migrations.AddField( - model_name='order', - name='promo_code', - field=models.ForeignKey(blank=True, help_text='optional promo code applied to this order', null=True, on_delete=django.db.models.deletion.PROTECT, to='core.promocode', verbose_name='applied promo code'), + model_name="order", + name="promo_code", + field=models.ForeignKey( + blank=True, + help_text="optional promo code applied to this order", + null=True, + on_delete=django.db.models.deletion.PROTECT, + to="core.promocode", + verbose_name="applied promo code", + ), ), migrations.AddField( - model_name='promotion', - name='products', - field=models.ManyToManyField(blank=True, help_text='select which products are included in this promotion', to='core.product', verbose_name='included products'), + model_name="promotion", + name="products", + field=models.ManyToManyField( + blank=True, + help_text="select which products are included in this promotion", + to="core.product", + verbose_name="included products", + ), ), migrations.AddField( - model_name='stock', - name='product', - field=models.ForeignKey(blank=True, help_text='the product associated with this stock entry', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stocks', to='core.product', verbose_name='associated product'), + model_name="stock", + name="product", + field=models.ForeignKey( + blank=True, + help_text="the product associated with this stock entry", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="stocks", + to="core.product", + verbose_name="associated product", + ), ), migrations.AddIndex( - model_name='vendor', - index=django.contrib.postgres.indexes.GinIndex(fields=['authentication'], name='core_vendor_authent_80dc1f_gin'), + model_name="vendor", + index=django.contrib.postgres.indexes.GinIndex( + fields=["authentication"], name="core_vendor_authent_80dc1f_gin" + ), ), migrations.AddField( - model_name='stock', - name='vendor', - field=models.ForeignKey(help_text='the vendor supplying this product stock', on_delete=django.db.models.deletion.CASCADE, to='core.vendor', verbose_name='associated vendor'), + model_name="stock", + name="vendor", + field=models.ForeignKey( + help_text="the vendor supplying this product stock", + on_delete=django.db.models.deletion.CASCADE, + to="core.vendor", + verbose_name="associated vendor", + ), ), migrations.AddField( - model_name='wishlist', - name='products', - field=models.ManyToManyField(blank=True, help_text='products that the user has marked as wanted', to='core.product', verbose_name='wishlisted products'), + model_name="wishlist", + name="products", + field=models.ManyToManyField( + blank=True, + help_text="products that the user has marked as wanted", + to="core.product", + verbose_name="wishlisted products", + ), ), migrations.AddField( - model_name='wishlist', - name='user', - field=models.OneToOneField(blank=True, help_text='user who owns this wishlist', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_related_wishlist', to=settings.AUTH_USER_MODEL, verbose_name='wishlist owner'), + model_name="wishlist", + name="user", + field=models.OneToOneField( + blank=True, + help_text="user who owns this wishlist", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="user_related_wishlist", + to=settings.AUTH_USER_MODEL, + verbose_name="wishlist owner", + ), ), migrations.AddIndex( - model_name='orderproduct', - index=django.contrib.postgres.indexes.GinIndex(fields=['notifications', 'attributes'], name='core_orderp_notific_cd27e9_gin'), + model_name="orderproduct", + index=django.contrib.postgres.indexes.GinIndex( + fields=["notifications", "attributes"], name="core_orderp_notific_cd27e9_gin" + ), ), ] diff --git a/core/migrations/0003_alter_attribute_name_alter_attribute_name_ar_ar_and_more.py b/core/migrations/0003_alter_attribute_name_alter_attribute_name_ar_ar_and_more.py index 769a5a5f..80caf008 100644 --- a/core/migrations/0003_alter_attribute_name_alter_attribute_name_ar_ar_and_more.py +++ b/core/migrations/0003_alter_attribute_name_alter_attribute_name_ar_ar_and_more.py @@ -4,495 +4,1054 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('core', '0002_initial'), + ("core", "0002_initial"), ] operations = [ migrations.AlterField( - model_name='attribute', - name='name', - field=models.CharField(help_text='name of this attribute', max_length=255, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_ar_AR', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_cs_CZ', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_da_DK', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_de_DE', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_en_GB', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_en_US', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_es_ES', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_fr_FR', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_hi_IN', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_it_IT', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_ja_JP', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_kk_KZ', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_nl_NL', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_pl_PL', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_pt_BR', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_ro_RO', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_ru_RU', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attribute', - name='name_zh_hans', - field=models.CharField(help_text='name of this attribute', max_length=255, null=True, unique=True, verbose_name="attribute's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name', - field=models.CharField(help_text="attribute group's name", max_length=255, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_ar_AR', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_cs_CZ', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_da_DK', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_de_DE', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_en_GB', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_en_US', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_es_ES', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_fr_FR', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_hi_IN', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_it_IT', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_ja_JP', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_kk_KZ', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_nl_NL', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_pl_PL', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_pt_BR', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_ro_RO', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_ru_RU', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='attributegroup', - name='name_zh_hans', - field=models.CharField(help_text="attribute group's name", max_length=255, null=True, unique=True, verbose_name="attribute group's name"), - ), - migrations.AlterField( - model_name='brand', - name='name', - field=models.CharField(help_text='name of this brand', max_length=255, unique=True, verbose_name='brand name'), - ), - migrations.AlterField( - model_name='category', - name='name', - field=models.CharField(help_text='provide a name for this category', max_length=255, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_ar_AR', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_cs_CZ', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_da_DK', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_de_DE', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_en_GB', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_en_US', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_es_ES', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_fr_FR', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_hi_IN', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_it_IT', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_ja_JP', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_kk_KZ', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_nl_NL', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_pl_PL', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_pt_BR', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_ro_RO', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_ru_RU', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='category', - name='name_zh_hans', - field=models.CharField(help_text='provide a name for this category', max_length=255, null=True, unique=True, verbose_name='category name'), - ), - migrations.AlterField( - model_name='product', - name='name', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_ar_AR', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_cs_CZ', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_da_DK', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_de_DE', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_en_GB', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_en_US', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_es_ES', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_fr_FR', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_hi_IN', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_it_IT', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_ja_JP', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_kk_KZ', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_nl_NL', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_pl_PL', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_pt_BR', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_ro_RO', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_ru_RU', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='product', - name='name_zh_hans', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, unique=True, verbose_name='product name'), - ), - migrations.AlterField( - model_name='producttag', - name='name', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_ar_AR', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_cs_CZ', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_da_DK', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_de_DE', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_en_GB', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_en_US', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_es_ES', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_fr_FR', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_hi_IN', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_it_IT', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_ja_JP', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_kk_KZ', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_nl_NL', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_pl_PL', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_pt_BR', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_ro_RO', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_ru_RU', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='producttag', - name='name_zh_hans', - field=models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, unique=True, verbose_name='tag display name'), - ), - migrations.AlterField( - model_name='vendor', - name='name', - field=models.CharField(help_text='name of this vendor', max_length=255, unique=True, verbose_name='vendor name'), + model_name="attribute", + name="name", + field=models.CharField( + help_text="name of this attribute", max_length=255, unique=True, verbose_name="attribute's name" + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_ar_AR", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_cs_CZ", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_da_DK", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_de_DE", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_en_GB", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_en_US", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_es_ES", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_fr_FR", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_hi_IN", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_it_IT", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_ja_JP", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_kk_KZ", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_nl_NL", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_pl_PL", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_pt_BR", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_ro_RO", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_ru_RU", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attribute", + name="name_zh_hans", + field=models.CharField( + help_text="name of this attribute", + max_length=255, + null=True, + unique=True, + verbose_name="attribute's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name", + field=models.CharField( + help_text="attribute group's name", max_length=255, unique=True, verbose_name="attribute group's name" + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_ar_AR", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_cs_CZ", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_da_DK", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_de_DE", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_en_GB", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_en_US", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_es_ES", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_fr_FR", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_hi_IN", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_it_IT", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_ja_JP", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_kk_KZ", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_nl_NL", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_pl_PL", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_pt_BR", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_ro_RO", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_ru_RU", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="attributegroup", + name="name_zh_hans", + field=models.CharField( + help_text="attribute group's name", + max_length=255, + null=True, + unique=True, + verbose_name="attribute group's name", + ), + ), + migrations.AlterField( + model_name="brand", + name="name", + field=models.CharField( + help_text="name of this brand", max_length=255, unique=True, verbose_name="brand name" + ), + ), + migrations.AlterField( + model_name="category", + name="name", + field=models.CharField( + help_text="provide a name for this category", max_length=255, unique=True, verbose_name="category name" + ), + ), + migrations.AlterField( + model_name="category", + name="name_ar_AR", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_cs_CZ", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_da_DK", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_de_DE", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_en_GB", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_en_US", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_es_ES", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_fr_FR", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_hi_IN", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_it_IT", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_ja_JP", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_kk_KZ", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_nl_NL", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_pl_PL", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_pt_BR", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_ro_RO", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_ru_RU", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="category", + name="name_zh_hans", + field=models.CharField( + help_text="provide a name for this category", + max_length=255, + null=True, + unique=True, + verbose_name="category name", + ), + ), + migrations.AlterField( + model_name="product", + name="name", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_ar_AR", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_cs_CZ", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_da_DK", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_de_DE", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_en_GB", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_en_US", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_es_ES", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_fr_FR", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_hi_IN", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_it_IT", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_ja_JP", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_kk_KZ", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_nl_NL", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_pl_PL", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_pt_BR", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_ro_RO", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_ru_RU", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="product", + name="name_zh_hans", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + unique=True, + verbose_name="product name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_ar_AR", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_cs_CZ", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_da_DK", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_de_DE", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_en_GB", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_en_US", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_es_ES", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_fr_FR", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_hi_IN", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_it_IT", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_ja_JP", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_kk_KZ", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_nl_NL", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_pl_PL", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_pt_BR", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_ro_RO", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_ru_RU", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="producttag", + name="name_zh_hans", + field=models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + migrations.AlterField( + model_name="vendor", + name="name", + field=models.CharField( + help_text="name of this vendor", max_length=255, unique=True, verbose_name="vendor name" + ), ), ] diff --git a/core/migrations/0004_alter_product_name_alter_product_name_ar_ar_and_more.py b/core/migrations/0004_alter_product_name_alter_product_name_ar_ar_and_more.py index 6e36c2d6..a47d03af 100644 --- a/core/migrations/0004_alter_product_name_alter_product_name_ar_ar_and_more.py +++ b/core/migrations/0004_alter_product_name_alter_product_name_ar_ar_and_more.py @@ -4,105 +4,198 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('core', '0003_alter_attribute_name_alter_attribute_name_ar_ar_and_more'), + ("core", "0003_alter_attribute_name_alter_attribute_name_ar_ar_and_more"), ] operations = [ migrations.AlterField( - model_name='product', - name='name', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, verbose_name='product name'), + model_name="product", + name="name", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_ar_AR', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_ar_AR", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_cs_CZ', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_cs_CZ", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_da_DK', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_da_DK", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_de_DE', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_de_DE", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_en_GB', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_en_GB", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_en_US', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_en_US", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_es_ES', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_es_ES", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_fr_FR', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_fr_FR", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_hi_IN', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_hi_IN", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_it_IT', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_it_IT", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_ja_JP', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_ja_JP", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_kk_KZ', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_kk_KZ", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_nl_NL', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_nl_NL", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_pl_PL', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_pl_PL", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_pt_BR', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_pt_BR", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_ro_RO', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_ro_RO", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_ru_RU', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_ru_RU", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), migrations.AlterField( - model_name='product', - name='name_zh_hans', - field=models.CharField(help_text='provide a clear identifying name for the product', max_length=255, null=True, verbose_name='product name'), + model_name="product", + name="name_zh_hans", + field=models.CharField( + help_text="provide a clear identifying name for the product", + max_length=255, + null=True, + verbose_name="product name", + ), ), ] diff --git a/core/migrations/0005_remove_brand_category_brand_categories.py b/core/migrations/0005_remove_brand_category_brand_categories.py index ed34cded..176538a3 100644 --- a/core/migrations/0005_remove_brand_category_brand_categories.py +++ b/core/migrations/0005_remove_brand_category_brand_categories.py @@ -4,19 +4,23 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('core', '0004_alter_product_name_alter_product_name_ar_ar_and_more'), + ("core", "0004_alter_product_name_alter_product_name_ar_ar_and_more"), ] operations = [ migrations.RemoveField( - model_name='brand', - name='category', + model_name="brand", + name="category", ), migrations.AddField( - model_name='brand', - name='categories', - field=models.ManyToManyField(blank=True, help_text='optional categories that this brand is associated with', to='core.category', verbose_name='associated categories'), + model_name="brand", + name="categories", + field=models.ManyToManyField( + blank=True, + help_text="optional categories that this brand is associated with", + to="core.category", + verbose_name="associated categories", + ), ), ] diff --git a/core/migrations/0006_alter_order_status.py b/core/migrations/0006_alter_order_status.py index 109fac86..41fd1bf9 100644 --- a/core/migrations/0006_alter_order_status.py +++ b/core/migrations/0006_alter_order_status.py @@ -4,15 +4,28 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('core', '0005_remove_brand_category_brand_categories'), + ("core", "0005_remove_brand_category_brand_categories"), ] operations = [ migrations.AlterField( - model_name='order', - name='status', - field=models.CharField(choices=[('PENDING', 'pending'), ('FAILED', 'failed'), ('PAYMENT', 'payment'), ('CREATED', 'created'), ('DELIVERING', 'delivering'), ('FINISHED', 'finished'), ('MOMENTAL', 'momental')], default='PENDING', help_text='current status of the order in its lifecycle', max_length=64, verbose_name='order status'), + model_name="order", + name="status", + field=models.CharField( + choices=[ + ("PENDING", "pending"), + ("FAILED", "failed"), + ("PAYMENT", "payment"), + ("CREATED", "created"), + ("DELIVERING", "delivering"), + ("FINISHED", "finished"), + ("MOMENTAL", "momental"), + ], + default="PENDING", + help_text="current status of the order in its lifecycle", + max_length=64, + verbose_name="order status", + ), ), ] diff --git a/core/migrations/0007_alter_category_image.py b/core/migrations/0007_alter_category_image.py index 25ffc9c1..77939b03 100644 --- a/core/migrations/0007_alter_category_image.py +++ b/core/migrations/0007_alter_category_image.py @@ -7,16 +7,20 @@ import core.validators class Migration(migrations.Migration): dependencies = [ - ('core', '0006_alter_order_status'), + ("core", "0006_alter_order_status"), ] operations = [ migrations.AlterField( - model_name='category', - name='image', - field=models.ImageField(blank=True, help_text='upload an image representing this category', null=True, - upload_to='categories/', - validators=[core.validators.validate_category_image_dimensions], - verbose_name='category image'), + model_name="category", + name="image", + field=models.ImageField( + blank=True, + help_text="upload an image representing this category", + null=True, + upload_to="categories/", + validators=[core.validators.validate_category_image_dimensions], + verbose_name="category image", + ), ), ] diff --git a/core/migrations/0008_digitalassetdownload.py b/core/migrations/0008_digitalassetdownload.py index 5739ebb5..32a3873e 100644 --- a/core/migrations/0008_digitalassetdownload.py +++ b/core/migrations/0008_digitalassetdownload.py @@ -9,33 +9,57 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('core', '0007_alter_category_image'), + ("core", "0007_alter_category_image"), ] operations = [ migrations.CreateModel( - name='DigitalAssetDownload', + name="DigitalAssetDownload", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('num_downloads', models.IntegerField(default=0)), - ('order_product', - models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='download', - to='core.orderproduct')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ("num_downloads", models.IntegerField(default=0)), + ( + "order_product", + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, related_name="download", to="core.orderproduct" + ), + ), ], options={ - 'verbose_name': 'download', - 'verbose_name_plural': 'downloads', + "verbose_name": "download", + "verbose_name_plural": "downloads", }, ), ] diff --git a/core/migrations/0009_documentary.py b/core/migrations/0009_documentary.py index d368b1c9..8beb86b4 100644 --- a/core/migrations/0009_documentary.py +++ b/core/migrations/0009_documentary.py @@ -11,32 +11,57 @@ import core.utils class Migration(migrations.Migration): dependencies = [ - ('core', '0008_digitalassetdownload'), + ("core", "0008_digitalassetdownload"), ] operations = [ migrations.CreateModel( - name='Documentary', + name="Documentary", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('document', models.FileField(upload_to=core.utils.get_product_uuid_as_path)), - ('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='documentaries', - to='core.product')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ("document", models.FileField(upload_to=core.utils.get_product_uuid_as_path)), + ( + "product", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name="documentaries", to="core.product" + ), + ), ], options={ - 'verbose_name': 'documentary', - 'verbose_name_plural': 'documentaries', + "verbose_name": "documentary", + "verbose_name_plural": "documentaries", }, ), ] diff --git a/core/migrations/0010_product_partnumber.py b/core/migrations/0010_product_partnumber.py index e447e697..3628270e 100644 --- a/core/migrations/0010_product_partnumber.py +++ b/core/migrations/0010_product_partnumber.py @@ -4,15 +4,20 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('core', '0009_documentary'), + ("core", "0009_documentary"), ] operations = [ migrations.AddField( - model_name='product', - name='partnumber', - field=models.CharField(default=None, help_text='part number for this product', null=True, unique=True, verbose_name='part number'), + model_name="product", + name="partnumber", + field=models.CharField( + default=None, + help_text="part number for this product", + null=True, + unique=True, + verbose_name="part number", + ), ), ] diff --git a/core/migrations/0011_brand_big_logo_brand_description_and_more.py b/core/migrations/0011_brand_big_logo_brand_description_and_more.py index 53e8890a..8dbb4df0 100644 --- a/core/migrations/0011_brand_big_logo_brand_description_and_more.py +++ b/core/migrations/0011_brand_big_logo_brand_description_and_more.py @@ -7,138 +7,222 @@ import core.validators class Migration(migrations.Migration): dependencies = [ - ('core', '0010_product_partnumber'), + ("core", "0010_product_partnumber"), ] operations = [ migrations.AddField( - model_name='brand', - name='big_logo', - field=models.ImageField(blank=True, help_text='upload a big logo representing this brand', null=True, - upload_to='brands/', - validators=[core.validators.validate_category_image_dimensions], - verbose_name='brand big image'), + model_name="brand", + name="big_logo", + field=models.ImageField( + blank=True, + help_text="upload a big logo representing this brand", + null=True, + upload_to="brands/", + validators=[core.validators.validate_category_image_dimensions], + verbose_name="brand big image", + ), ), migrations.AddField( - model_name='brand', - name='description', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_ar_AR', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_ar_AR", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_cs_CZ', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_cs_CZ", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_da_DK', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_da_DK", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_de_DE', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_de_DE", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_en_GB', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_en_GB", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_en_US', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_en_US", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_es_ES', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_es_ES", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_fr_FR', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_fr_FR", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_hi_IN', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_hi_IN", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_it_IT', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_it_IT", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_ja_JP', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_ja_JP", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_kk_KZ', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_kk_KZ", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_nl_NL', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_nl_NL", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_pl_PL', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_pl_PL", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_pt_BR', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_pt_BR", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_ro_RO', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_ro_RO", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_ru_RU', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_ru_RU", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='description_zh_hans', - field=models.TextField(blank=True, help_text='add a detailed description of the brand', null=True, - verbose_name='brand description'), + model_name="brand", + name="description_zh_hans", + field=models.TextField( + blank=True, + help_text="add a detailed description of the brand", + null=True, + verbose_name="brand description", + ), ), migrations.AddField( - model_name='brand', - name='small_logo', - field=models.ImageField(blank=True, help_text='upload a logo representing this brand', null=True, - upload_to='brands/', - validators=[core.validators.validate_category_image_dimensions], - verbose_name='brand small image'), + model_name="brand", + name="small_logo", + field=models.ImageField( + blank=True, + help_text="upload a logo representing this brand", + null=True, + upload_to="brands/", + validators=[core.validators.validate_category_image_dimensions], + verbose_name="brand small image", + ), ), ] diff --git a/core/migrations/0012_alter_order_user.py b/core/migrations/0012_alter_order_user.py index 97465a31..2213f5ab 100644 --- a/core/migrations/0012_alter_order_user.py +++ b/core/migrations/0012_alter_order_user.py @@ -6,16 +6,23 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('core', '0011_brand_big_logo_brand_description_and_more'), + ("core", "0011_brand_big_logo_brand_description_and_more"), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.AlterField( - model_name='order', - name='user', - field=models.ForeignKey(blank=True, help_text='the user who placed the order', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='orders', to=settings.AUTH_USER_MODEL, verbose_name='user'), + model_name="order", + name="user", + field=models.ForeignKey( + blank=True, + help_text="the user who placed the order", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="orders", + to=settings.AUTH_USER_MODEL, + verbose_name="user", + ), ), ] diff --git a/core/migrations/0013_product_slug.py b/core/migrations/0013_product_slug.py index fbf8b75f..412aeef4 100644 --- a/core/migrations/0013_product_slug.py +++ b/core/migrations/0013_product_slug.py @@ -5,15 +5,21 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ - ('core', '0012_alter_order_user'), + ("core", "0012_alter_order_user"), ] operations = [ migrations.AddField( - model_name='product', - name='slug', - field=django_extensions.db.fields.AutoSlugField(allow_unicode=True, null=True, blank=True, editable=False, populate_from=('category.name', 'brand.name', 'name'), unique=True), + model_name="product", + name="slug", + field=django_extensions.db.fields.AutoSlugField( + allow_unicode=True, + null=True, + blank=True, + editable=False, + populate_from=("category.name", "brand.name", "name"), + unique=True, + ), ), ] diff --git a/core/migrations/0014_alter_product_slug.py b/core/migrations/0014_alter_product_slug.py index b1b5f7f4..db3fba48 100644 --- a/core/migrations/0014_alter_product_slug.py +++ b/core/migrations/0014_alter_product_slug.py @@ -5,15 +5,21 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ - ('core', '0013_product_slug'), + ("core", "0013_product_slug"), ] operations = [ migrations.AlterField( - model_name='product', - name='slug', - field=django_extensions.db.fields.AutoSlugField(allow_unicode=True, blank=True, editable=False, null=True, populate_from=('uuid', 'category.name', 'brand.name', 'name'), unique=True), + model_name="product", + name="slug", + field=django_extensions.db.fields.AutoSlugField( + allow_unicode=True, + blank=True, + editable=False, + null=True, + populate_from=("uuid", "category.name", "brand.name", "name"), + unique=True, + ), ), ] diff --git a/core/migrations/0015_alter_product_slug.py b/core/migrations/0015_alter_product_slug.py index 5cd41799..d0d284bf 100644 --- a/core/migrations/0015_alter_product_slug.py +++ b/core/migrations/0015_alter_product_slug.py @@ -5,15 +5,21 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ - ('core', '0014_alter_product_slug'), + ("core", "0014_alter_product_slug"), ] operations = [ migrations.AlterField( - model_name='product', - name='slug', - field=django_extensions.db.fields.AutoSlugField(allow_unicode=True, blank=True, editable=False, null=True, populate_from=('category__name', 'name'), unique=True), + model_name="product", + name="slug", + field=django_extensions.db.fields.AutoSlugField( + allow_unicode=True, + blank=True, + editable=False, + null=True, + populate_from=("category__name", "name"), + unique=True, + ), ), ] diff --git a/core/migrations/0016_alter_product_slug.py b/core/migrations/0016_alter_product_slug.py index 32875776..01ed1c17 100644 --- a/core/migrations/0016_alter_product_slug.py +++ b/core/migrations/0016_alter_product_slug.py @@ -5,15 +5,21 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ - ('core', '0015_alter_product_slug'), + ("core", "0015_alter_product_slug"), ] operations = [ migrations.AlterField( - model_name='product', - name='slug', - field=django_extensions.db.fields.AutoSlugField(allow_unicode=True, blank=True, editable=False, null=True, populate_from=('uuid', 'category__name', 'name'), unique=True), + model_name="product", + name="slug", + field=django_extensions.db.fields.AutoSlugField( + allow_unicode=True, + blank=True, + editable=False, + null=True, + populate_from=("uuid", "category__name", "name"), + unique=True, + ), ), ] diff --git a/core/migrations/0017_order_human_readable_id.py b/core/migrations/0017_order_human_readable_id.py index 48d73cb0..36572585 100644 --- a/core/migrations/0017_order_human_readable_id.py +++ b/core/migrations/0017_order_human_readable_id.py @@ -7,15 +7,18 @@ import core.utils class Migration(migrations.Migration): dependencies = [ - ('core', '0016_alter_product_slug'), + ("core", "0016_alter_product_slug"), ] operations = [ migrations.AddField( - model_name='order', - name='human_readable_id', - field=models.CharField(default=core.utils.generate_human_readable_id, - help_text='a human-readable identifier for the order', max_length=8, - verbose_name='human readable id'), + model_name="order", + name="human_readable_id", + field=models.CharField( + default=core.utils.generate_human_readable_id, + help_text="a human-readable identifier for the order", + max_length=8, + verbose_name="human readable id", + ), ), ] diff --git a/core/migrations/0018_alter_order_human_readable_id.py b/core/migrations/0018_alter_order_human_readable_id.py index 10f7899f..5fe3e70a 100644 --- a/core/migrations/0018_alter_order_human_readable_id.py +++ b/core/migrations/0018_alter_order_human_readable_id.py @@ -8,11 +8,7 @@ def fix_duplicates(apps, schema_editor): if schema_editor: pass Order = apps.get_model("core", "Order") - duplicates = ( - Order.objects.values("human_readable_id") - .annotate(count=Count("uuid")) - .filter(count__gt=1) - ) + duplicates = Order.objects.values("human_readable_id").annotate(count=Count("uuid")).filter(count__gt=1) for duplicate in duplicates: h_id = duplicate["human_readable_id"] orders = Order.objects.filter(human_readable_id=h_id).order_by("uuid") @@ -20,6 +16,7 @@ def fix_duplicates(apps, schema_editor): new_id = order.human_readable_id while Order.objects.filter(human_readable_id=new_id).exists(): from core.utils import generate_human_readable_id + new_id = generate_human_readable_id() order.human_readable_id = new_id order.save() @@ -35,16 +32,20 @@ def reverse_func(apps, schema_editor): class Migration(migrations.Migration): dependencies = [ - ('core', '0017_order_human_readable_id'), + ("core", "0017_order_human_readable_id"), ] operations = [ migrations.RunPython(fix_duplicates, reverse_func), migrations.AlterField( - model_name='order', - name='human_readable_id', - field=models.CharField(default=core.utils.generate_human_readable_id, - help_text='a human-readable identifier for the order', max_length=8, unique=True, - verbose_name='human readable id'), + model_name="order", + name="human_readable_id", + field=models.CharField( + default=core.utils.generate_human_readable_id, + help_text="a human-readable identifier for the order", + max_length=8, + unique=True, + verbose_name="human readable id", + ), ), ] diff --git a/core/migrations/0019_address.py b/core/migrations/0019_address.py index 229c86c6..1c3bce8e 100644 --- a/core/migrations/0019_address.py +++ b/core/migrations/0019_address.py @@ -11,46 +11,86 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('core', '0018_alter_order_human_readable_id'), + ("core", "0018_alter_order_human_readable_id"), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( - name='Address', + name="Address", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('street', models.CharField(max_length=255, null=True, verbose_name='street')), - ('district', models.CharField(max_length=255, null=True, verbose_name='district')), - ('city', models.CharField(max_length=100, null=True, verbose_name='city')), - ('region', models.CharField(max_length=100, null=True, verbose_name='region')), - ('postal_code', models.CharField(max_length=20, null=True, verbose_name='postal code')), - ('country', models.CharField(max_length=40, null=True, verbose_name='country')), - ('location', django.contrib.gis.db.models.fields.PointField(blank=True, geography=True, - help_text='geolocation point: (longitude, latitude)', - null=True, srid=4326)), - ('raw_data', models.JSONField(blank=True, help_text='full JSON response from geocoder for this address', - null=True)), - ('api_response', - models.JSONField(blank=True, help_text='stored JSON response from the geocoding service', null=True)), - ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, - to=settings.AUTH_USER_MODEL)), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ("street", models.CharField(max_length=255, null=True, verbose_name="street")), + ("district", models.CharField(max_length=255, null=True, verbose_name="district")), + ("city", models.CharField(max_length=100, null=True, verbose_name="city")), + ("region", models.CharField(max_length=100, null=True, verbose_name="region")), + ("postal_code", models.CharField(max_length=20, null=True, verbose_name="postal code")), + ("country", models.CharField(max_length=40, null=True, verbose_name="country")), + ( + "location", + django.contrib.gis.db.models.fields.PointField( + blank=True, + geography=True, + help_text="geolocation point: (longitude, latitude)", + null=True, + srid=4326, + ), + ), + ( + "raw_data", + models.JSONField( + blank=True, help_text="full JSON response from geocoder for this address", null=True + ), + ), + ( + "api_response", + models.JSONField( + blank=True, help_text="stored JSON response from the geocoding service", null=True + ), + ), + ( + "user", + models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL + ), + ), ], options={ - 'verbose_name': 'address', - 'verbose_name_plural': 'addresses', - 'indexes': [models.Index(fields=['location'], name='core_addres_locatio_eb6b39_idx')], + "verbose_name": "address", + "verbose_name_plural": "addresses", + "indexes": [models.Index(fields=["location"], name="core_addres_locatio_eb6b39_idx")], }, ), ] diff --git a/core/migrations/0020_order_billing_address_order_shipping_address.py b/core/migrations/0020_order_billing_address_order_shipping_address.py index 430b124e..718186f0 100644 --- a/core/migrations/0020_order_billing_address_order_shipping_address.py +++ b/core/migrations/0020_order_billing_address_order_shipping_address.py @@ -5,7 +5,7 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('core', '0019_address'), + ("core", "0019_address"), ] operations = [ @@ -17,29 +17,30 @@ class Migration(migrations.Migration): ), reverse_sql=migrations.RunSQL.noop, ), - migrations.AddField( - model_name='order', - name='billing_address', + model_name="order", + name="billing_address", field=models.ForeignKey( - blank=True, null=True, + blank=True, + null=True, on_delete=models.deletion.CASCADE, - related_name='billing_address_order', - to='core.address', - verbose_name='billing address', - help_text='the billing address used for this order', + related_name="billing_address_order", + to="core.address", + verbose_name="billing address", + help_text="the billing address used for this order", ), ), migrations.AddField( - model_name='order', - name='shipping_address', + model_name="order", + name="shipping_address", field=models.ForeignKey( - blank=True, null=True, + blank=True, + null=True, on_delete=models.deletion.CASCADE, - related_name='shipping_address_order', - to='core.address', - verbose_name='shipping address', - help_text='the shipping address used for this order', + related_name="shipping_address_order", + to="core.address", + verbose_name="shipping address", + help_text="the shipping address used for this order", ), ), ] diff --git a/core/migrations/0021_rename_name_ar_ar_attribute_name_ar_ar_and_more.py b/core/migrations/0021_rename_name_ar_ar_attribute_name_ar_ar_and_more.py index ca4135dd..26e88bd0 100644 --- a/core/migrations/0021_rename_name_ar_ar_attribute_name_ar_ar_and_more.py +++ b/core/migrations/0021_rename_name_ar_ar_attribute_name_ar_ar_and_more.py @@ -5,943 +5,943 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('core', '0020_order_billing_address_order_shipping_address'), + ("core", "0020_order_billing_address_order_shipping_address"), ] operations = [ migrations.RenameField( - model_name='attribute', - old_name='name_ar_AR', - new_name='name_ar_ar', + model_name="attribute", + old_name="name_ar_AR", + new_name="name_ar_ar", ), migrations.RenameField( - model_name='attribute', - old_name='name_cs_CZ', - new_name='name_cs_cz', + model_name="attribute", + old_name="name_cs_CZ", + new_name="name_cs_cz", ), migrations.RenameField( - model_name='attribute', - old_name='name_da_DK', - new_name='name_da_dk', + model_name="attribute", + old_name="name_da_DK", + new_name="name_da_dk", ), migrations.RenameField( - model_name='attribute', - old_name='name_de_DE', - new_name='name_de_de', + model_name="attribute", + old_name="name_de_DE", + new_name="name_de_de", ), migrations.RenameField( - model_name='attribute', - old_name='name_en_GB', - new_name='name_en_gb', + model_name="attribute", + old_name="name_en_GB", + new_name="name_en_gb", ), migrations.RenameField( - model_name='attribute', - old_name='name_en_US', - new_name='name_en_us', + model_name="attribute", + old_name="name_en_US", + new_name="name_en_us", ), migrations.RenameField( - model_name='attribute', - old_name='name_es_ES', - new_name='name_es_es', + model_name="attribute", + old_name="name_es_ES", + new_name="name_es_es", ), migrations.RenameField( - model_name='attribute', - old_name='name_fr_FR', - new_name='name_fr_fr', + model_name="attribute", + old_name="name_fr_FR", + new_name="name_fr_fr", ), migrations.RenameField( - model_name='attribute', - old_name='name_hi_IN', - new_name='name_hi_in', + model_name="attribute", + old_name="name_hi_IN", + new_name="name_hi_in", ), migrations.RenameField( - model_name='attribute', - old_name='name_it_IT', - new_name='name_it_it', + model_name="attribute", + old_name="name_it_IT", + new_name="name_it_it", ), migrations.RenameField( - model_name='attribute', - old_name='name_ja_JP', - new_name='name_ja_jp', + model_name="attribute", + old_name="name_ja_JP", + new_name="name_ja_jp", ), migrations.RenameField( - model_name='attribute', - old_name='name_kk_KZ', - new_name='name_kk_kz', + model_name="attribute", + old_name="name_kk_KZ", + new_name="name_kk_kz", ), migrations.RenameField( - model_name='attribute', - old_name='name_nl_NL', - new_name='name_nl_nl', + model_name="attribute", + old_name="name_nl_NL", + new_name="name_nl_nl", ), migrations.RenameField( - model_name='attribute', - old_name='name_pl_PL', - new_name='name_pl_pl', + model_name="attribute", + old_name="name_pl_PL", + new_name="name_pl_pl", ), migrations.RenameField( - model_name='attribute', - old_name='name_pt_BR', - new_name='name_pt_br', + model_name="attribute", + old_name="name_pt_BR", + new_name="name_pt_br", ), migrations.RenameField( - model_name='attribute', - old_name='name_ro_RO', - new_name='name_ro_ro', + model_name="attribute", + old_name="name_ro_RO", + new_name="name_ro_ro", ), migrations.RenameField( - model_name='attribute', - old_name='name_ru_RU', - new_name='name_ru_ru', + model_name="attribute", + old_name="name_ru_RU", + new_name="name_ru_ru", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_ar_AR', - new_name='name_ar_ar', + model_name="attributegroup", + old_name="name_ar_AR", + new_name="name_ar_ar", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_cs_CZ', - new_name='name_cs_cz', + model_name="attributegroup", + old_name="name_cs_CZ", + new_name="name_cs_cz", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_da_DK', - new_name='name_da_dk', + model_name="attributegroup", + old_name="name_da_DK", + new_name="name_da_dk", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_de_DE', - new_name='name_de_de', + model_name="attributegroup", + old_name="name_de_DE", + new_name="name_de_de", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_en_GB', - new_name='name_en_gb', + model_name="attributegroup", + old_name="name_en_GB", + new_name="name_en_gb", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_en_US', - new_name='name_en_us', + model_name="attributegroup", + old_name="name_en_US", + new_name="name_en_us", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_es_ES', - new_name='name_es_es', + model_name="attributegroup", + old_name="name_es_ES", + new_name="name_es_es", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_fr_FR', - new_name='name_fr_fr', + model_name="attributegroup", + old_name="name_fr_FR", + new_name="name_fr_fr", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_hi_IN', - new_name='name_hi_in', + model_name="attributegroup", + old_name="name_hi_IN", + new_name="name_hi_in", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_it_IT', - new_name='name_it_it', + model_name="attributegroup", + old_name="name_it_IT", + new_name="name_it_it", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_ja_JP', - new_name='name_ja_jp', + model_name="attributegroup", + old_name="name_ja_JP", + new_name="name_ja_jp", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_kk_KZ', - new_name='name_kk_kz', + model_name="attributegroup", + old_name="name_kk_KZ", + new_name="name_kk_kz", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_nl_NL', - new_name='name_nl_nl', + model_name="attributegroup", + old_name="name_nl_NL", + new_name="name_nl_nl", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_pl_PL', - new_name='name_pl_pl', + model_name="attributegroup", + old_name="name_pl_PL", + new_name="name_pl_pl", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_pt_BR', - new_name='name_pt_br', + model_name="attributegroup", + old_name="name_pt_BR", + new_name="name_pt_br", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_ro_RO', - new_name='name_ro_ro', + model_name="attributegroup", + old_name="name_ro_RO", + new_name="name_ro_ro", ), migrations.RenameField( - model_name='attributegroup', - old_name='name_ru_RU', - new_name='name_ru_ru', + model_name="attributegroup", + old_name="name_ru_RU", + new_name="name_ru_ru", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_ar_AR', - new_name='value_ar_ar', + model_name="attributevalue", + old_name="value_ar_AR", + new_name="value_ar_ar", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_cs_CZ', - new_name='value_cs_cz', + model_name="attributevalue", + old_name="value_cs_CZ", + new_name="value_cs_cz", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_da_DK', - new_name='value_da_dk', + model_name="attributevalue", + old_name="value_da_DK", + new_name="value_da_dk", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_de_DE', - new_name='value_de_de', + model_name="attributevalue", + old_name="value_de_DE", + new_name="value_de_de", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_en_GB', - new_name='value_en_gb', + model_name="attributevalue", + old_name="value_en_GB", + new_name="value_en_gb", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_en_US', - new_name='value_en_us', + model_name="attributevalue", + old_name="value_en_US", + new_name="value_en_us", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_es_ES', - new_name='value_es_es', + model_name="attributevalue", + old_name="value_es_ES", + new_name="value_es_es", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_fr_FR', - new_name='value_fr_fr', + model_name="attributevalue", + old_name="value_fr_FR", + new_name="value_fr_fr", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_hi_IN', - new_name='value_hi_in', + model_name="attributevalue", + old_name="value_hi_IN", + new_name="value_hi_in", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_it_IT', - new_name='value_it_it', + model_name="attributevalue", + old_name="value_it_IT", + new_name="value_it_it", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_ja_JP', - new_name='value_ja_jp', + model_name="attributevalue", + old_name="value_ja_JP", + new_name="value_ja_jp", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_kk_KZ', - new_name='value_kk_kz', + model_name="attributevalue", + old_name="value_kk_KZ", + new_name="value_kk_kz", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_nl_NL', - new_name='value_nl_nl', + model_name="attributevalue", + old_name="value_nl_NL", + new_name="value_nl_nl", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_pl_PL', - new_name='value_pl_pl', + model_name="attributevalue", + old_name="value_pl_PL", + new_name="value_pl_pl", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_pt_BR', - new_name='value_pt_br', + model_name="attributevalue", + old_name="value_pt_BR", + new_name="value_pt_br", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_ro_RO', - new_name='value_ro_ro', + model_name="attributevalue", + old_name="value_ro_RO", + new_name="value_ro_ro", ), migrations.RenameField( - model_name='attributevalue', - old_name='value_ru_RU', - new_name='value_ru_ru', + model_name="attributevalue", + old_name="value_ru_RU", + new_name="value_ru_ru", ), migrations.RenameField( - model_name='brand', - old_name='description_ar_AR', - new_name='description_ar_ar', + model_name="brand", + old_name="description_ar_AR", + new_name="description_ar_ar", ), migrations.RenameField( - model_name='brand', - old_name='description_cs_CZ', - new_name='description_cs_cz', + model_name="brand", + old_name="description_cs_CZ", + new_name="description_cs_cz", ), migrations.RenameField( - model_name='brand', - old_name='description_da_DK', - new_name='description_da_dk', + model_name="brand", + old_name="description_da_DK", + new_name="description_da_dk", ), migrations.RenameField( - model_name='brand', - old_name='description_de_DE', - new_name='description_de_de', + model_name="brand", + old_name="description_de_DE", + new_name="description_de_de", ), migrations.RenameField( - model_name='brand', - old_name='description_en_GB', - new_name='description_en_gb', + model_name="brand", + old_name="description_en_GB", + new_name="description_en_gb", ), migrations.RenameField( - model_name='brand', - old_name='description_en_US', - new_name='description_en_us', + model_name="brand", + old_name="description_en_US", + new_name="description_en_us", ), migrations.RenameField( - model_name='brand', - old_name='description_es_ES', - new_name='description_es_es', + model_name="brand", + old_name="description_es_ES", + new_name="description_es_es", ), migrations.RenameField( - model_name='brand', - old_name='description_fr_FR', - new_name='description_fr_fr', + model_name="brand", + old_name="description_fr_FR", + new_name="description_fr_fr", ), migrations.RenameField( - model_name='brand', - old_name='description_hi_IN', - new_name='description_hi_in', + model_name="brand", + old_name="description_hi_IN", + new_name="description_hi_in", ), migrations.RenameField( - model_name='brand', - old_name='description_it_IT', - new_name='description_it_it', + model_name="brand", + old_name="description_it_IT", + new_name="description_it_it", ), migrations.RenameField( - model_name='brand', - old_name='description_ja_JP', - new_name='description_ja_jp', + model_name="brand", + old_name="description_ja_JP", + new_name="description_ja_jp", ), migrations.RenameField( - model_name='brand', - old_name='description_kk_KZ', - new_name='description_kk_kz', + model_name="brand", + old_name="description_kk_KZ", + new_name="description_kk_kz", ), migrations.RenameField( - model_name='brand', - old_name='description_nl_NL', - new_name='description_nl_nl', + model_name="brand", + old_name="description_nl_NL", + new_name="description_nl_nl", ), migrations.RenameField( - model_name='brand', - old_name='description_pl_PL', - new_name='description_pl_pl', + model_name="brand", + old_name="description_pl_PL", + new_name="description_pl_pl", ), migrations.RenameField( - model_name='brand', - old_name='description_pt_BR', - new_name='description_pt_br', + model_name="brand", + old_name="description_pt_BR", + new_name="description_pt_br", ), migrations.RenameField( - model_name='brand', - old_name='description_ro_RO', - new_name='description_ro_ro', + model_name="brand", + old_name="description_ro_RO", + new_name="description_ro_ro", ), migrations.RenameField( - model_name='brand', - old_name='description_ru_RU', - new_name='description_ru_ru', + model_name="brand", + old_name="description_ru_RU", + new_name="description_ru_ru", ), migrations.RenameField( - model_name='category', - old_name='description_ar_AR', - new_name='description_ar_ar', + model_name="category", + old_name="description_ar_AR", + new_name="description_ar_ar", ), migrations.RenameField( - model_name='category', - old_name='description_cs_CZ', - new_name='description_cs_cz', + model_name="category", + old_name="description_cs_CZ", + new_name="description_cs_cz", ), migrations.RenameField( - model_name='category', - old_name='description_da_DK', - new_name='description_da_dk', + model_name="category", + old_name="description_da_DK", + new_name="description_da_dk", ), migrations.RenameField( - model_name='category', - old_name='description_de_DE', - new_name='description_de_de', + model_name="category", + old_name="description_de_DE", + new_name="description_de_de", ), migrations.RenameField( - model_name='category', - old_name='description_en_GB', - new_name='description_en_gb', + model_name="category", + old_name="description_en_GB", + new_name="description_en_gb", ), migrations.RenameField( - model_name='category', - old_name='description_en_US', - new_name='description_en_us', + model_name="category", + old_name="description_en_US", + new_name="description_en_us", ), migrations.RenameField( - model_name='category', - old_name='description_es_ES', - new_name='description_es_es', + model_name="category", + old_name="description_es_ES", + new_name="description_es_es", ), migrations.RenameField( - model_name='category', - old_name='description_fr_FR', - new_name='description_fr_fr', + model_name="category", + old_name="description_fr_FR", + new_name="description_fr_fr", ), migrations.RenameField( - model_name='category', - old_name='description_hi_IN', - new_name='description_hi_in', + model_name="category", + old_name="description_hi_IN", + new_name="description_hi_in", ), migrations.RenameField( - model_name='category', - old_name='description_it_IT', - new_name='description_it_it', + model_name="category", + old_name="description_it_IT", + new_name="description_it_it", ), migrations.RenameField( - model_name='category', - old_name='description_ja_JP', - new_name='description_ja_jp', + model_name="category", + old_name="description_ja_JP", + new_name="description_ja_jp", ), migrations.RenameField( - model_name='category', - old_name='description_kk_KZ', - new_name='description_kk_kz', + model_name="category", + old_name="description_kk_KZ", + new_name="description_kk_kz", ), migrations.RenameField( - model_name='category', - old_name='description_nl_NL', - new_name='description_nl_nl', + model_name="category", + old_name="description_nl_NL", + new_name="description_nl_nl", ), migrations.RenameField( - model_name='category', - old_name='description_pl_PL', - new_name='description_pl_pl', + model_name="category", + old_name="description_pl_PL", + new_name="description_pl_pl", ), migrations.RenameField( - model_name='category', - old_name='description_pt_BR', - new_name='description_pt_br', + model_name="category", + old_name="description_pt_BR", + new_name="description_pt_br", ), migrations.RenameField( - model_name='category', - old_name='description_ro_RO', - new_name='description_ro_ro', + model_name="category", + old_name="description_ro_RO", + new_name="description_ro_ro", ), migrations.RenameField( - model_name='category', - old_name='description_ru_RU', - new_name='description_ru_ru', + model_name="category", + old_name="description_ru_RU", + new_name="description_ru_ru", ), migrations.RenameField( - model_name='category', - old_name='name_ar_AR', - new_name='name_ar_ar', + model_name="category", + old_name="name_ar_AR", + new_name="name_ar_ar", ), migrations.RenameField( - model_name='category', - old_name='name_cs_CZ', - new_name='name_cs_cz', + model_name="category", + old_name="name_cs_CZ", + new_name="name_cs_cz", ), migrations.RenameField( - model_name='category', - old_name='name_da_DK', - new_name='name_da_dk', + model_name="category", + old_name="name_da_DK", + new_name="name_da_dk", ), migrations.RenameField( - model_name='category', - old_name='name_de_DE', - new_name='name_de_de', + model_name="category", + old_name="name_de_DE", + new_name="name_de_de", ), migrations.RenameField( - model_name='category', - old_name='name_en_GB', - new_name='name_en_gb', + model_name="category", + old_name="name_en_GB", + new_name="name_en_gb", ), migrations.RenameField( - model_name='category', - old_name='name_en_US', - new_name='name_en_us', + model_name="category", + old_name="name_en_US", + new_name="name_en_us", ), migrations.RenameField( - model_name='category', - old_name='name_es_ES', - new_name='name_es_es', + model_name="category", + old_name="name_es_ES", + new_name="name_es_es", ), migrations.RenameField( - model_name='category', - old_name='name_fr_FR', - new_name='name_fr_fr', + model_name="category", + old_name="name_fr_FR", + new_name="name_fr_fr", ), migrations.RenameField( - model_name='category', - old_name='name_hi_IN', - new_name='name_hi_in', + model_name="category", + old_name="name_hi_IN", + new_name="name_hi_in", ), migrations.RenameField( - model_name='category', - old_name='name_it_IT', - new_name='name_it_it', + model_name="category", + old_name="name_it_IT", + new_name="name_it_it", ), migrations.RenameField( - model_name='category', - old_name='name_ja_JP', - new_name='name_ja_jp', + model_name="category", + old_name="name_ja_JP", + new_name="name_ja_jp", ), migrations.RenameField( - model_name='category', - old_name='name_kk_KZ', - new_name='name_kk_kz', + model_name="category", + old_name="name_kk_KZ", + new_name="name_kk_kz", ), migrations.RenameField( - model_name='category', - old_name='name_nl_NL', - new_name='name_nl_nl', + model_name="category", + old_name="name_nl_NL", + new_name="name_nl_nl", ), migrations.RenameField( - model_name='category', - old_name='name_pl_PL', - new_name='name_pl_pl', + model_name="category", + old_name="name_pl_PL", + new_name="name_pl_pl", ), migrations.RenameField( - model_name='category', - old_name='name_pt_BR', - new_name='name_pt_br', + model_name="category", + old_name="name_pt_BR", + new_name="name_pt_br", ), migrations.RenameField( - model_name='category', - old_name='name_ro_RO', - new_name='name_ro_ro', + model_name="category", + old_name="name_ro_RO", + new_name="name_ro_ro", ), migrations.RenameField( - model_name='category', - old_name='name_ru_RU', - new_name='name_ru_ru', + model_name="category", + old_name="name_ru_RU", + new_name="name_ru_ru", ), migrations.RenameField( - model_name='product', - old_name='description_ar_AR', - new_name='description_ar_ar', + model_name="product", + old_name="description_ar_AR", + new_name="description_ar_ar", ), migrations.RenameField( - model_name='product', - old_name='description_cs_CZ', - new_name='description_cs_cz', + model_name="product", + old_name="description_cs_CZ", + new_name="description_cs_cz", ), migrations.RenameField( - model_name='product', - old_name='description_da_DK', - new_name='description_da_dk', + model_name="product", + old_name="description_da_DK", + new_name="description_da_dk", ), migrations.RenameField( - model_name='product', - old_name='description_de_DE', - new_name='description_de_de', + model_name="product", + old_name="description_de_DE", + new_name="description_de_de", ), migrations.RenameField( - model_name='product', - old_name='description_en_GB', - new_name='description_en_gb', + model_name="product", + old_name="description_en_GB", + new_name="description_en_gb", ), migrations.RenameField( - model_name='product', - old_name='description_en_US', - new_name='description_en_us', + model_name="product", + old_name="description_en_US", + new_name="description_en_us", ), migrations.RenameField( - model_name='product', - old_name='description_es_ES', - new_name='description_es_es', + model_name="product", + old_name="description_es_ES", + new_name="description_es_es", ), migrations.RenameField( - model_name='product', - old_name='description_fr_FR', - new_name='description_fr_fr', + model_name="product", + old_name="description_fr_FR", + new_name="description_fr_fr", ), migrations.RenameField( - model_name='product', - old_name='description_hi_IN', - new_name='description_hi_in', + model_name="product", + old_name="description_hi_IN", + new_name="description_hi_in", ), migrations.RenameField( - model_name='product', - old_name='description_it_IT', - new_name='description_it_it', + model_name="product", + old_name="description_it_IT", + new_name="description_it_it", ), migrations.RenameField( - model_name='product', - old_name='description_ja_JP', - new_name='description_ja_jp', + model_name="product", + old_name="description_ja_JP", + new_name="description_ja_jp", ), migrations.RenameField( - model_name='product', - old_name='description_kk_KZ', - new_name='description_kk_kz', + model_name="product", + old_name="description_kk_KZ", + new_name="description_kk_kz", ), migrations.RenameField( - model_name='product', - old_name='description_nl_NL', - new_name='description_nl_nl', + model_name="product", + old_name="description_nl_NL", + new_name="description_nl_nl", ), migrations.RenameField( - model_name='product', - old_name='description_pl_PL', - new_name='description_pl_pl', + model_name="product", + old_name="description_pl_PL", + new_name="description_pl_pl", ), migrations.RenameField( - model_name='product', - old_name='description_pt_BR', - new_name='description_pt_br', + model_name="product", + old_name="description_pt_BR", + new_name="description_pt_br", ), migrations.RenameField( - model_name='product', - old_name='description_ro_RO', - new_name='description_ro_ro', + model_name="product", + old_name="description_ro_RO", + new_name="description_ro_ro", ), migrations.RenameField( - model_name='product', - old_name='description_ru_RU', - new_name='description_ru_ru', + model_name="product", + old_name="description_ru_RU", + new_name="description_ru_ru", ), migrations.RenameField( - model_name='product', - old_name='name_ar_AR', - new_name='name_ar_ar', + model_name="product", + old_name="name_ar_AR", + new_name="name_ar_ar", ), migrations.RenameField( - model_name='product', - old_name='name_cs_CZ', - new_name='name_cs_cz', + model_name="product", + old_name="name_cs_CZ", + new_name="name_cs_cz", ), migrations.RenameField( - model_name='product', - old_name='name_da_DK', - new_name='name_da_dk', + model_name="product", + old_name="name_da_DK", + new_name="name_da_dk", ), migrations.RenameField( - model_name='product', - old_name='name_de_DE', - new_name='name_de_de', + model_name="product", + old_name="name_de_DE", + new_name="name_de_de", ), migrations.RenameField( - model_name='product', - old_name='name_en_GB', - new_name='name_en_gb', + model_name="product", + old_name="name_en_GB", + new_name="name_en_gb", ), migrations.RenameField( - model_name='product', - old_name='name_en_US', - new_name='name_en_us', + model_name="product", + old_name="name_en_US", + new_name="name_en_us", ), migrations.RenameField( - model_name='product', - old_name='name_es_ES', - new_name='name_es_es', + model_name="product", + old_name="name_es_ES", + new_name="name_es_es", ), migrations.RenameField( - model_name='product', - old_name='name_fr_FR', - new_name='name_fr_fr', + model_name="product", + old_name="name_fr_FR", + new_name="name_fr_fr", ), migrations.RenameField( - model_name='product', - old_name='name_hi_IN', - new_name='name_hi_in', + model_name="product", + old_name="name_hi_IN", + new_name="name_hi_in", ), migrations.RenameField( - model_name='product', - old_name='name_it_IT', - new_name='name_it_it', + model_name="product", + old_name="name_it_IT", + new_name="name_it_it", ), migrations.RenameField( - model_name='product', - old_name='name_ja_JP', - new_name='name_ja_jp', + model_name="product", + old_name="name_ja_JP", + new_name="name_ja_jp", ), migrations.RenameField( - model_name='product', - old_name='name_kk_KZ', - new_name='name_kk_kz', + model_name="product", + old_name="name_kk_KZ", + new_name="name_kk_kz", ), migrations.RenameField( - model_name='product', - old_name='name_nl_NL', - new_name='name_nl_nl', + model_name="product", + old_name="name_nl_NL", + new_name="name_nl_nl", ), migrations.RenameField( - model_name='product', - old_name='name_pl_PL', - new_name='name_pl_pl', + model_name="product", + old_name="name_pl_PL", + new_name="name_pl_pl", ), migrations.RenameField( - model_name='product', - old_name='name_pt_BR', - new_name='name_pt_br', + model_name="product", + old_name="name_pt_BR", + new_name="name_pt_br", ), migrations.RenameField( - model_name='product', - old_name='name_ro_RO', - new_name='name_ro_ro', + model_name="product", + old_name="name_ro_RO", + new_name="name_ro_ro", ), migrations.RenameField( - model_name='product', - old_name='name_ru_RU', - new_name='name_ru_ru', + model_name="product", + old_name="name_ru_RU", + new_name="name_ru_ru", ), migrations.RenameField( - model_name='producttag', - old_name='name_ar_AR', - new_name='name_ar_ar', + model_name="producttag", + old_name="name_ar_AR", + new_name="name_ar_ar", ), migrations.RenameField( - model_name='producttag', - old_name='name_cs_CZ', - new_name='name_cs_cz', + model_name="producttag", + old_name="name_cs_CZ", + new_name="name_cs_cz", ), migrations.RenameField( - model_name='producttag', - old_name='name_da_DK', - new_name='name_da_dk', + model_name="producttag", + old_name="name_da_DK", + new_name="name_da_dk", ), migrations.RenameField( - model_name='producttag', - old_name='name_de_DE', - new_name='name_de_de', + model_name="producttag", + old_name="name_de_DE", + new_name="name_de_de", ), migrations.RenameField( - model_name='producttag', - old_name='name_en_GB', - new_name='name_en_gb', + model_name="producttag", + old_name="name_en_GB", + new_name="name_en_gb", ), migrations.RenameField( - model_name='producttag', - old_name='name_en_US', - new_name='name_en_us', + model_name="producttag", + old_name="name_en_US", + new_name="name_en_us", ), migrations.RenameField( - model_name='producttag', - old_name='name_es_ES', - new_name='name_es_es', + model_name="producttag", + old_name="name_es_ES", + new_name="name_es_es", ), migrations.RenameField( - model_name='producttag', - old_name='name_fr_FR', - new_name='name_fr_fr', + model_name="producttag", + old_name="name_fr_FR", + new_name="name_fr_fr", ), migrations.RenameField( - model_name='producttag', - old_name='name_hi_IN', - new_name='name_hi_in', + model_name="producttag", + old_name="name_hi_IN", + new_name="name_hi_in", ), migrations.RenameField( - model_name='producttag', - old_name='name_it_IT', - new_name='name_it_it', + model_name="producttag", + old_name="name_it_IT", + new_name="name_it_it", ), migrations.RenameField( - model_name='producttag', - old_name='name_ja_JP', - new_name='name_ja_jp', + model_name="producttag", + old_name="name_ja_JP", + new_name="name_ja_jp", ), migrations.RenameField( - model_name='producttag', - old_name='name_kk_KZ', - new_name='name_kk_kz', + model_name="producttag", + old_name="name_kk_KZ", + new_name="name_kk_kz", ), migrations.RenameField( - model_name='producttag', - old_name='name_nl_NL', - new_name='name_nl_nl', + model_name="producttag", + old_name="name_nl_NL", + new_name="name_nl_nl", ), migrations.RenameField( - model_name='producttag', - old_name='name_pl_PL', - new_name='name_pl_pl', + model_name="producttag", + old_name="name_pl_PL", + new_name="name_pl_pl", ), migrations.RenameField( - model_name='producttag', - old_name='name_pt_BR', - new_name='name_pt_br', + model_name="producttag", + old_name="name_pt_BR", + new_name="name_pt_br", ), migrations.RenameField( - model_name='producttag', - old_name='name_ro_RO', - new_name='name_ro_ro', + model_name="producttag", + old_name="name_ro_RO", + new_name="name_ro_ro", ), migrations.RenameField( - model_name='producttag', - old_name='name_ru_RU', - new_name='name_ru_ru', + model_name="producttag", + old_name="name_ru_RU", + new_name="name_ru_ru", ), migrations.RenameField( - model_name='promotion', - old_name='description_ar_AR', - new_name='description_ar_ar', + model_name="promotion", + old_name="description_ar_AR", + new_name="description_ar_ar", ), migrations.RenameField( - model_name='promotion', - old_name='description_cs_CZ', - new_name='description_cs_cz', + model_name="promotion", + old_name="description_cs_CZ", + new_name="description_cs_cz", ), migrations.RenameField( - model_name='promotion', - old_name='description_da_DK', - new_name='description_da_dk', + model_name="promotion", + old_name="description_da_DK", + new_name="description_da_dk", ), migrations.RenameField( - model_name='promotion', - old_name='description_de_DE', - new_name='description_de_de', + model_name="promotion", + old_name="description_de_DE", + new_name="description_de_de", ), migrations.RenameField( - model_name='promotion', - old_name='description_en_GB', - new_name='description_en_gb', + model_name="promotion", + old_name="description_en_GB", + new_name="description_en_gb", ), migrations.RenameField( - model_name='promotion', - old_name='description_en_US', - new_name='description_en_us', + model_name="promotion", + old_name="description_en_US", + new_name="description_en_us", ), migrations.RenameField( - model_name='promotion', - old_name='description_es_ES', - new_name='description_es_es', + model_name="promotion", + old_name="description_es_ES", + new_name="description_es_es", ), migrations.RenameField( - model_name='promotion', - old_name='description_fr_FR', - new_name='description_fr_fr', + model_name="promotion", + old_name="description_fr_FR", + new_name="description_fr_fr", ), migrations.RenameField( - model_name='promotion', - old_name='description_hi_IN', - new_name='description_hi_in', + model_name="promotion", + old_name="description_hi_IN", + new_name="description_hi_in", ), migrations.RenameField( - model_name='promotion', - old_name='description_it_IT', - new_name='description_it_it', + model_name="promotion", + old_name="description_it_IT", + new_name="description_it_it", ), migrations.RenameField( - model_name='promotion', - old_name='description_ja_JP', - new_name='description_ja_jp', + model_name="promotion", + old_name="description_ja_JP", + new_name="description_ja_jp", ), migrations.RenameField( - model_name='promotion', - old_name='description_kk_KZ', - new_name='description_kk_kz', + model_name="promotion", + old_name="description_kk_KZ", + new_name="description_kk_kz", ), migrations.RenameField( - model_name='promotion', - old_name='description_nl_NL', - new_name='description_nl_nl', + model_name="promotion", + old_name="description_nl_NL", + new_name="description_nl_nl", ), migrations.RenameField( - model_name='promotion', - old_name='description_pl_PL', - new_name='description_pl_pl', + model_name="promotion", + old_name="description_pl_PL", + new_name="description_pl_pl", ), migrations.RenameField( - model_name='promotion', - old_name='description_pt_BR', - new_name='description_pt_br', + model_name="promotion", + old_name="description_pt_BR", + new_name="description_pt_br", ), migrations.RenameField( - model_name='promotion', - old_name='description_ro_RO', - new_name='description_ro_ro', + model_name="promotion", + old_name="description_ro_RO", + new_name="description_ro_ro", ), migrations.RenameField( - model_name='promotion', - old_name='description_ru_RU', - new_name='description_ru_ru', + model_name="promotion", + old_name="description_ru_RU", + new_name="description_ru_ru", ), migrations.RenameField( - model_name='promotion', - old_name='name_ar_AR', - new_name='name_ar_ar', + model_name="promotion", + old_name="name_ar_AR", + new_name="name_ar_ar", ), migrations.RenameField( - model_name='promotion', - old_name='name_cs_CZ', - new_name='name_cs_cz', + model_name="promotion", + old_name="name_cs_CZ", + new_name="name_cs_cz", ), migrations.RenameField( - model_name='promotion', - old_name='name_da_DK', - new_name='name_da_dk', + model_name="promotion", + old_name="name_da_DK", + new_name="name_da_dk", ), migrations.RenameField( - model_name='promotion', - old_name='name_de_DE', - new_name='name_de_de', + model_name="promotion", + old_name="name_de_DE", + new_name="name_de_de", ), migrations.RenameField( - model_name='promotion', - old_name='name_en_GB', - new_name='name_en_gb', + model_name="promotion", + old_name="name_en_GB", + new_name="name_en_gb", ), migrations.RenameField( - model_name='promotion', - old_name='name_en_US', - new_name='name_en_us', + model_name="promotion", + old_name="name_en_US", + new_name="name_en_us", ), migrations.RenameField( - model_name='promotion', - old_name='name_es_ES', - new_name='name_es_es', + model_name="promotion", + old_name="name_es_ES", + new_name="name_es_es", ), migrations.RenameField( - model_name='promotion', - old_name='name_fr_FR', - new_name='name_fr_fr', + model_name="promotion", + old_name="name_fr_FR", + new_name="name_fr_fr", ), migrations.RenameField( - model_name='promotion', - old_name='name_hi_IN', - new_name='name_hi_in', + model_name="promotion", + old_name="name_hi_IN", + new_name="name_hi_in", ), migrations.RenameField( - model_name='promotion', - old_name='name_it_IT', - new_name='name_it_it', + model_name="promotion", + old_name="name_it_IT", + new_name="name_it_it", ), migrations.RenameField( - model_name='promotion', - old_name='name_ja_JP', - new_name='name_ja_jp', + model_name="promotion", + old_name="name_ja_JP", + new_name="name_ja_jp", ), migrations.RenameField( - model_name='promotion', - old_name='name_kk_KZ', - new_name='name_kk_kz', + model_name="promotion", + old_name="name_kk_KZ", + new_name="name_kk_kz", ), migrations.RenameField( - model_name='promotion', - old_name='name_nl_NL', - new_name='name_nl_nl', + model_name="promotion", + old_name="name_nl_NL", + new_name="name_nl_nl", ), migrations.RenameField( - model_name='promotion', - old_name='name_pl_PL', - new_name='name_pl_pl', + model_name="promotion", + old_name="name_pl_PL", + new_name="name_pl_pl", ), migrations.RenameField( - model_name='promotion', - old_name='name_pt_BR', - new_name='name_pt_br', + model_name="promotion", + old_name="name_pt_BR", + new_name="name_pt_br", ), migrations.RenameField( - model_name='promotion', - old_name='name_ro_RO', - new_name='name_ro_ro', + model_name="promotion", + old_name="name_ro_RO", + new_name="name_ro_ro", ), migrations.RenameField( - model_name='promotion', - old_name='name_ru_RU', - new_name='name_ru_ru', + model_name="promotion", + old_name="name_ru_RU", + new_name="name_ru_ru", ), ] diff --git a/core/migrations/0022_category_slug.py b/core/migrations/0022_category_slug.py index fe1e3b26..cd887039 100644 --- a/core/migrations/0022_category_slug.py +++ b/core/migrations/0022_category_slug.py @@ -7,7 +7,7 @@ from django.db import migrations def populate_slugs(apps, schema_editor): if schema_editor: pass - Category = apps.get_model('core', 'Category') + Category = apps.get_model("core", "Category") for category in Category.objects.all(): try: if not category.slug: @@ -18,15 +18,16 @@ def populate_slugs(apps, schema_editor): class Migration(migrations.Migration): dependencies = [ - ('core', '0021_rename_name_ar_ar_attribute_name_ar_ar_and_more'), + ("core", "0021_rename_name_ar_ar_attribute_name_ar_ar_and_more"), ] operations = [ migrations.AddField( - model_name='category', - name='slug', - field=django_extensions.db.fields.AutoSlugField(allow_unicode=True, blank=True, editable=False, null=True, - populate_from=('uuid', 'name'), unique=True), + model_name="category", + name="slug", + field=django_extensions.db.fields.AutoSlugField( + allow_unicode=True, blank=True, editable=False, null=True, populate_from=("uuid", "name"), unique=True + ), ), migrations.RunPython(populate_slugs, reverse_code=migrations.RunPython.noop), ] diff --git a/core/migrations/0023_address_address_line.py b/core/migrations/0023_address_address_line.py index 55654c18..e1f6ebf4 100644 --- a/core/migrations/0023_address_address_line.py +++ b/core/migrations/0023_address_address_line.py @@ -5,14 +5,15 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('core', '0022_category_slug'), + ("core", "0022_category_slug"), ] operations = [ migrations.AddField( - model_name='address', - name='address_line', - field=models.TextField(blank=True, help_text='address line for the customer', null=True, - verbose_name='address line'), + model_name="address", + name="address_line", + field=models.TextField( + blank=True, help_text="address line for the customer", null=True, verbose_name="address line" + ), ), ] diff --git a/core/migrations/0024_categorytag_category_tags.py b/core/migrations/0024_categorytag_category_tags.py index 9b140e9a..71a220aa 100644 --- a/core/migrations/0024_categorytag_category_tags.py +++ b/core/migrations/0024_categorytag_category_tags.py @@ -9,95 +9,256 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('core', '0023_address_address_line'), + ("core", "0023_address_address_line"), ] operations = [ migrations.CreateModel( - name='CategoryTag', + name="CategoryTag", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('tag_name', models.CharField(help_text='internal tag identifier for the product tag', max_length=255, - verbose_name='tag name')), - ('name', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, unique=True, - verbose_name='tag display name')), - ('name_en_gb', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_ar_ar', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_cs_cz', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_da_dk', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_de_de', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_en_us', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_es_es', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_fr_fr', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_hi_in', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_it_it', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_ja_jp', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_kk_kz', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_nl_nl', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_pl_pl', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_pt_br', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_ro_ro', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_ru_ru', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), - ('name_zh_hans', - models.CharField(help_text='user-friendly name for the product tag', max_length=255, null=True, - unique=True, verbose_name='tag display name')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "tag_name", + models.CharField( + help_text="internal tag identifier for the product tag", max_length=255, verbose_name="tag name" + ), + ), + ( + "name", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_en_gb", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_ar_ar", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_cs_cz", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_da_dk", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_de_de", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_en_us", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_es_es", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_fr_fr", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_hi_in", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_it_it", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_ja_jp", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_kk_kz", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_nl_nl", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_pl_pl", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_pt_br", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_ro_ro", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_ru_ru", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), + ( + "name_zh_hans", + models.CharField( + help_text="user-friendly name for the product tag", + max_length=255, + null=True, + unique=True, + verbose_name="tag display name", + ), + ), ], options={ - 'verbose_name': 'category tag', - 'verbose_name_plural': 'category tags', + "verbose_name": "category tag", + "verbose_name_plural": "category tags", }, - bases=(django_prometheus.models.ExportModelOperationsMixin('category_tag'), models.Model), + bases=(django_prometheus.models.ExportModelOperationsMixin("category_tag"), models.Model), ), migrations.AddField( - model_name='category', - name='tags', - field=models.ManyToManyField(blank=True, help_text='tags that help describe or group this category', - to='core.categorytag', verbose_name='category tags'), + model_name="category", + name="tags", + field=models.ManyToManyField( + blank=True, + help_text="tags that help describe or group this category", + to="core.categorytag", + verbose_name="category tags", + ), ), ] diff --git a/core/migrations/0025_alter_product_category.py b/core/migrations/0025_alter_product_category.py index 4e6cc22d..f524aef9 100644 --- a/core/migrations/0025_alter_product_category.py +++ b/core/migrations/0025_alter_product_category.py @@ -6,15 +6,19 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('core', '0024_categorytag_category_tags'), + ("core", "0024_categorytag_category_tags"), ] operations = [ migrations.AlterField( - model_name='product', - name='category', - field=models.ForeignKey(help_text='category this product belongs to', - on_delete=django.db.models.deletion.CASCADE, related_name='products', - to='core.category', verbose_name='category'), + model_name="product", + name="category", + field=models.ForeignKey( + help_text="category this product belongs to", + on_delete=django.db.models.deletion.CASCADE, + related_name="products", + to="core.category", + verbose_name="category", + ), ), ] diff --git a/core/migrations/0026_brand_slug_alter_category_slug_alter_product_slug.py b/core/migrations/0026_brand_slug_alter_category_slug_alter_product_slug.py index 3a0a57b3..39905993 100644 --- a/core/migrations/0026_brand_slug_alter_category_slug_alter_product_slug.py +++ b/core/migrations/0026_brand_slug_alter_category_slug_alter_product_slug.py @@ -5,7 +5,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ("core", "0025_alter_product_category"), ] diff --git a/core/migrations/0027_brand_priority_alter_brand_slug.py b/core/migrations/0027_brand_priority_alter_brand_slug.py index 0aca9c40..5427bc2c 100644 --- a/core/migrations/0027_brand_priority_alter_brand_slug.py +++ b/core/migrations/0027_brand_priority_alter_brand_slug.py @@ -5,7 +5,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ("core", "0026_brand_slug_alter_category_slug_alter_product_slug"), ] diff --git a/core/migrations/0028_alter_category_slug_alter_product_slug.py b/core/migrations/0028_alter_category_slug_alter_product_slug.py index e14befd4..552057fa 100644 --- a/core/migrations/0028_alter_category_slug_alter_product_slug.py +++ b/core/migrations/0028_alter_category_slug_alter_product_slug.py @@ -5,7 +5,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ("core", "0027_brand_priority_alter_brand_slug"), ] diff --git a/core/migrations/0029_alter_category_slug.py b/core/migrations/0029_alter_category_slug.py index 1c11d24d..d0ef9170 100644 --- a/core/migrations/0029_alter_category_slug.py +++ b/core/migrations/0029_alter_category_slug.py @@ -5,7 +5,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ("core", "0028_alter_category_slug_alter_product_slug"), ] diff --git a/core/migrations/0030_alter_category_slug.py b/core/migrations/0030_alter_category_slug.py index b46497e8..8ad88128 100644 --- a/core/migrations/0030_alter_category_slug.py +++ b/core/migrations/0030_alter_category_slug.py @@ -5,7 +5,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ("core", "0029_alter_category_slug"), ] diff --git a/core/migrations/0031_alter_product_slug.py b/core/migrations/0031_alter_product_slug.py index cebf2052..39b0fa1b 100644 --- a/core/migrations/0031_alter_product_slug.py +++ b/core/migrations/0031_alter_product_slug.py @@ -5,7 +5,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ("core", "0030_alter_category_slug"), ] diff --git a/core/migrations/0032_alter_brand_slug_alter_category_slug_and_more.py b/core/migrations/0032_alter_brand_slug_alter_category_slug_and_more.py index 237c5935..eb6005ab 100644 --- a/core/migrations/0032_alter_brand_slug_alter_category_slug_and_more.py +++ b/core/migrations/0032_alter_brand_slug_alter_category_slug_and_more.py @@ -5,7 +5,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ("core", "0031_alter_product_slug"), ] diff --git a/core/migrations/0033_alter_category_slug.py b/core/migrations/0033_alter_category_slug.py index 034beed6..a022aba5 100644 --- a/core/migrations/0033_alter_category_slug.py +++ b/core/migrations/0033_alter_category_slug.py @@ -6,7 +6,6 @@ import core.utils.db class Migration(migrations.Migration): - dependencies = [ ("core", "0032_alter_brand_slug_alter_category_slug_and_more"), ] diff --git a/core/migrations/0034_category_priority_alter_brand_priority.py b/core/migrations/0034_category_priority_alter_brand_priority.py index cd64f3f1..08c161fe 100644 --- a/core/migrations/0034_category_priority_alter_brand_priority.py +++ b/core/migrations/0034_category_priority_alter_brand_priority.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ("core", "0033_alter_category_slug"), ] diff --git a/core/migrations/0035_alter_brand_slug_alter_category_slug_and_more.py b/core/migrations/0035_alter_brand_slug_alter_category_slug_and_more.py new file mode 100644 index 00000000..16a5702d --- /dev/null +++ b/core/migrations/0035_alter_brand_slug_alter_category_slug_and_more.py @@ -0,0 +1,59 @@ +# Generated by Django 5.2 on 2025-06-29 13:09 + +import core.utils.db +import django_extensions.db.fields +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0034_category_priority_alter_brand_priority"), + ] + + operations = [ + migrations.AlterField( + model_name="brand", + name="slug", + field=django_extensions.db.fields.AutoSlugField( + allow_unicode=True, + blank=True, + editable=False, + max_length=88, + null=True, + overwrite=True, + populate_from=("name",), + unique=True, + verbose_name="Slug", + ), + ), + migrations.AlterField( + model_name="category", + name="slug", + field=core.utils.db.TweakedAutoSlugField( + allow_unicode=True, + blank=True, + editable=False, + max_length=88, + null=True, + overwrite=True, + populate_from=("parent__name", "name"), + unique=True, + verbose_name="Slug", + ), + ), + migrations.AlterField( + model_name="product", + name="slug", + field=django_extensions.db.fields.AutoSlugField( + allow_unicode=True, + blank=True, + editable=False, + max_length=88, + null=True, + overwrite=True, + populate_from=("name", "brand__slug", "category__slug", "uuid"), + unique=True, + verbose_name="Slug", + ), + ), + ] diff --git a/core/migrations/0036_vendor_b2b_auth_token_vendor_users.py b/core/migrations/0036_vendor_b2b_auth_token_vendor_users.py new file mode 100644 index 00000000..0d2c74a2 --- /dev/null +++ b/core/migrations/0036_vendor_b2b_auth_token_vendor_users.py @@ -0,0 +1,30 @@ +# Generated by Django 5.2 on 2025-07-28 08:55 + +import core.utils +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0035_alter_brand_slug_alter_category_slug_and_more"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AddField( + model_name="vendor", + name="b2b_auth_token", + field=models.CharField( + blank=True, + default=core.utils.generate_human_readable_token, + max_length=20, + null=True, + ), + ), + migrations.AddField( + model_name="vendor", + name="users", + field=models.ManyToManyField(blank=True, related_name="vendors", to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/core/models.py b/core/models.py index 2e8e637a..dca0c750 100644 --- a/core/models.py +++ b/core/models.py @@ -1,15 +1,17 @@ import datetime import json import logging -from decimal import Decimal -from typing import Optional, Self +from typing import Any, Optional, Self from constance import config +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType from django.contrib.gis.db.models import PointField from django.contrib.postgres.indexes import GinIndex from django.core.cache import cache from django.core.exceptions import BadRequest, ValidationError from django.core.validators import MaxValueValidator, MinValueValidator +from django.db import transaction from django.db.models import ( CASCADE, PROTECT, @@ -28,7 +30,10 @@ from django.db.models import ( Max, OneToOneField, PositiveIntegerField, + QuerySet, TextField, + UUIDField, + URLField, ) from django.db.models.indexes import Index from django.http import Http404 @@ -49,6 +54,7 @@ from core.utils import ( generate_human_readable_id, get_product_uuid_as_path, get_random_code, + generate_human_readable_token, ) from core.utils.db import TweakedAutoSlugField, unicode_slugify_function from core.utils.lists import FAILED_STATUSES @@ -56,13 +62,39 @@ from core.validators import validate_category_image_dimensions from evibes.settings import CURRENCY_CODE from payments.models import Transaction -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") -class AttributeGroup(ExportModelOperationsMixin("attribute_group"), NiceModel): +class AttributeGroup(ExportModelOperationsMixin("attribute_group"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents a group of attributes, which can be hierarchical. + + This class is used to manage and organize attribute groups. An attribute + group can have a parent group, forming a hierarchical structure. This can + be useful for categorizing and managing attributes more effectively in a + complex system. + + Attributes: + parent (Self): A foreign key referencing the parent of this group. It + can be null or blank if the group does not have a parent. The parent + group organizes the hierarchical structure. + name (str): The unique name of the attribute group. It is limited to a + maximum of 255 characters. + is_publicly_visible (bool): Indicates if the attribute group is visible + publicly. + + Meta: + verbose_name: A human-readable name for the class, set to 'attribute + group'. + verbose_name_plural: A human-readable plural name for the class, set to + 'attribute groups'. + """ + is_publicly_visible = True + attributes: QuerySet["Attribute"] + children: QuerySet["Self"] - parent: Self = ForeignKey( # type: ignore + parent = ForeignKey( "self", on_delete=CASCADE, null=True, @@ -71,7 +103,7 @@ class AttributeGroup(ExportModelOperationsMixin("attribute_group"), NiceModel): help_text=_("parent of this group"), verbose_name=_("parent attribute group"), ) - name: str = CharField( # type: ignore + name = CharField( max_length=255, verbose_name=_("attribute group's name"), help_text=_("attribute group's name"), @@ -86,24 +118,50 @@ class AttributeGroup(ExportModelOperationsMixin("attribute_group"), NiceModel): verbose_name_plural = _("attribute groups") -class Vendor(ExportModelOperationsMixin("vendor"), NiceModel): +class Vendor(ExportModelOperationsMixin("vendor"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + 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. + It stores the vendor's name, authentication details required for communication, + and the percentage markup applied to products retrieved from the vendor. This model also + maintains additional metadata and constraints, making it suitable for use in systems + that interact with third-party vendors. + + Attributes: + authentication (dict): Credentials and endpoint information required for vendor + communication, stored in a JSON field. + markup_percent (int): The markup percentage applied to products sent by this + vendor. Must be an integer between 0 and 100 inclusive. + name (str): The unique name of the vendor, with a maximum length of 255 + characters. + + Meta: + verbose_name (str): Singular name of the vendor entity ("vendor"). + verbose_name_plural (str): Plural name of the vendor entities ("vendors"). + indexes (list): List of database indexes applied to this model, including a + GIN index on the 'authentication' field. + + Returns: + str: The vendor's name when the instance is represented as a string. + """ + is_publicly_visible = False - authentication: dict = JSONField( # type: ignore + authentication = JSONField( blank=True, null=True, - help_text=_( - "stores credentials and endpoints required for vendor communication" - ), + help_text=_("stores credentials and endpoints required for vendor communication"), verbose_name=_("authentication info"), ) - markup_percent: int = IntegerField( # type: ignore + markup_percent = IntegerField( default=0, validators=[MinValueValidator(0), MaxValueValidator(100)], help_text=_("define the markup for products retrieved from this vendor"), verbose_name=_("vendor markup percentage"), ) - name: str = CharField( # type: ignore + name = CharField( max_length=255, help_text=_("name of this vendor"), verbose_name=_("vendor name"), @@ -111,10 +169,23 @@ class Vendor(ExportModelOperationsMixin("vendor"), NiceModel): null=False, unique=True, ) + users = ManyToManyField(to="vibes_auth.User", related_name="vendors", blank=True) + b2b_auth_token = CharField(default=generate_human_readable_token, max_length=20, null=True, blank=True) def __str__(self) -> str: return self.name + def save(self, **kwargs) -> None: + users = self.users.filter(is_active=True) + users = users.exclude(attributes__icontains="is_business") + if users.count() > 0: + for user in users: + if not user.attributes: + user.attributes = {} + user.attributes.update({"is_business": True}) + user.save() + return super().save(**kwargs) + class Meta: verbose_name = _("vendor") verbose_name_plural = _("vendors") @@ -123,17 +194,33 @@ class Vendor(ExportModelOperationsMixin("vendor"), NiceModel): ] -class ProductTag(ExportModelOperationsMixin("product_tag"), NiceModel): +class ProductTag(ExportModelOperationsMixin("product_tag"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents a product tag used for classifying or identifying products. + + 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. It supports operations exported through mixins and provides + metadata customization for administrative purposes. + + Attributes: + is_publicly_visible: A boolean indicating whether the tag is publicly + visible. + tag_name: Internal tag identifier for the product tag. + name: User-friendly name for the product tag. + + """ + is_publicly_visible = True - tag_name: str = CharField( # type: ignore + tag_name = CharField( blank=False, null=False, max_length=255, help_text=_("internal tag identifier for the product tag"), verbose_name=_("tag name"), ) - name: str = CharField( # type: ignore + name = CharField( max_length=255, help_text=_("user-friendly name for the product tag"), verbose_name=_("tag display name"), @@ -148,17 +235,30 @@ class ProductTag(ExportModelOperationsMixin("product_tag"), NiceModel): verbose_name_plural = _("product tags") -class CategoryTag(ExportModelOperationsMixin("category_tag"), NiceModel): +class CategoryTag(ExportModelOperationsMixin("category_tag"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents a category tag used for 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. + + Attributes: + is_publicly_visible (bool): Indicates if the category tag is publicly visible. + tag_name (str): Internal tag identifier for the product tag. + name (str): User-friendly name for the product tag. + + """ + is_publicly_visible = True - tag_name: str = CharField( # type: ignore + tag_name = CharField( blank=False, null=False, max_length=255, help_text=_("internal tag identifier for the product tag"), verbose_name=_("tag name"), ) - name: str = CharField( # type: ignore + name = CharField( max_length=255, help_text=_("user-friendly name for the product tag"), verbose_name=_("tag display name"), @@ -173,10 +273,77 @@ class CategoryTag(ExportModelOperationsMixin("category_tag"), NiceModel): verbose_name_plural = _("category tags") -class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): +class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): # type: ignore [misc, django-manager-missing] + """ + 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. The class includes fields for metadata and + visual representation, which serve as a foundation for category-related features. + + This class is typically used to define and manage product categories or other similar + groupings within an application, allowing users or administrators to specify the + name, description, and hierarchy of categories, as well as assign attributes like + images, tags, or priority. + + Attributes + ---------- + is_publicly_visible + A flag indicating whether the category is visible to the public. + + image : ImageField + Represents an optional image associated with the category. The image is used + to visually represent the category. + + markup_percent + Specifies the markup percentage for products in this category. It is validated + to ensure values fall between 0 and 100. + + parent + Represents the parent category in a hierarchical structure. This forms category + relationships to enable nesting. + + name + The name of the category, which also must be unique. This serves as the primary + identifier for the category. + + description + An optional detailed description explaining the purpose or details of the category. + + slug + A unique, auto-generated field created from the category's name and parent name, + suitable for use in URLs and identifying the category. + + tags + Optional tags used to group or describe the category better. + + priority + Represents the priority of the category, which could be used for sorting or + rendering purposes. + + Methods + ------- + __str__() + Returns the name of the category as its string representation. + + get_tree_depth() + Computes the depth of the category in the hierarchical structure. It determines + the maximum depth of its descendants or returns zero if the category is a leaf. + + ------------ + verbose_name + Specifies the singular human-readable name for the category model. + + verbose_name_plural + Specifies the plural human-readable name for the category model. + + ordering : list + Defines the default ordering for category instances, based on their hierarchical + structure. + """ + is_publicly_visible = True - image = ImageField( # type: ignore + image = ImageField( blank=True, null=True, help_text=_("upload an image representing this category"), @@ -184,13 +351,13 @@ class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): validators=[validate_category_image_dimensions], verbose_name=_("category image"), ) - markup_percent: int = IntegerField( # type: ignore + markup_percent = IntegerField( default=0, validators=[MinValueValidator(0), MaxValueValidator(100)], help_text=_("define a markup percentage for products in this category"), verbose_name=_("markup percentage"), ) - parent: Self = TreeForeignKey( + parent = TreeForeignKey( "self", on_delete=CASCADE, blank=True, @@ -200,21 +367,21 @@ class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): verbose_name=_("parent category"), ) - name: str = CharField( # type: ignore + name = CharField( max_length=255, verbose_name=_("category name"), help_text=_("provide a name for this category"), unique=True, ) - description: str = TextField( # type: ignore + description = TextField( blank=True, null=True, help_text=_("add a detailed description for this category"), verbose_name=_("category description"), ) - slug: str = TweakedAutoSlugField( # type: ignore + slug = TweakedAutoSlugField( populate_from=( "parent__name", "name", @@ -228,13 +395,13 @@ class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): null=True, verbose_name=_("Slug"), ) - tags: CategoryTag = ManyToManyField( # type: ignore + tags = ManyToManyField( "core.CategoryTag", blank=True, help_text=_("tags that help describe or group this category"), verbose_name=_("category tags"), ) - priority: int = PositiveIntegerField( # type: ignore + priority = PositiveIntegerField( default=0, null=False, blank=False, @@ -247,10 +414,7 @@ class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): def get_tree_depth(self): if self.is_leaf_node(): return 0 - return ( - self.get_descendants().aggregate(max_depth=Max("level"))["max_depth"] - - self.get_level() - ) + return self.get_descendants().aggregate(max_depth=Max("level"))["max_depth"] - self.get_level() class Meta: verbose_name = _("category") @@ -258,16 +422,35 @@ class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): ordering = ["tree_id", "lft"] -class Brand(ExportModelOperationsMixin("brand"), NiceModel): +class Brand(ExportModelOperationsMixin("brand"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents a Brand object in the system. + + This class handles information and attributes related to a brand, including its name, logos, + description, associated categories, a unique slug, and priority order. + 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 - name: str = CharField( # type: ignore + name = CharField( max_length=255, help_text=_("name of this brand"), verbose_name=_("brand name"), unique=True, ) - small_logo = ImageField( # type: ignore + small_logo = ImageField( upload_to="brands/", blank=True, null=True, @@ -275,7 +458,7 @@ class Brand(ExportModelOperationsMixin("brand"), NiceModel): validators=[validate_category_image_dimensions], verbose_name=_("brand small image"), ) - big_logo = ImageField( # type: ignore + big_logo = ImageField( upload_to="brands/", blank=True, null=True, @@ -283,19 +466,19 @@ class Brand(ExportModelOperationsMixin("brand"), NiceModel): validators=[validate_category_image_dimensions], verbose_name=_("brand big image"), ) - description: str = TextField( # type: ignore + description = TextField( blank=True, null=True, help_text=_("add a detailed description of the brand"), verbose_name=_("brand description"), ) - categories: Category = ManyToManyField( # type: ignore + categories = ManyToManyField( "core.Category", blank=True, help_text=_("optional categories that this brand is associated with"), verbose_name=_("associated categories"), ) - slug: str = AutoSlugField( # type: ignore + slug = AutoSlugField( populate_from=("name",), allow_unicode=True, unique=True, @@ -306,7 +489,7 @@ class Brand(ExportModelOperationsMixin("brand"), NiceModel): slugify_function=unicode_slugify_function, verbose_name=_("Slug"), ) - priority: int = PositiveIntegerField( # type: ignore + priority = PositiveIntegerField( default=0, null=False, blank=False, @@ -321,17 +504,127 @@ class Brand(ExportModelOperationsMixin("brand"), NiceModel): verbose_name_plural = _("brands") -class Product(ExportModelOperationsMixin("product"), NiceModel): +class Stock(ExportModelOperationsMixin("stock"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents the stock of a product managed in the system. + + 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. It is part of the inventory + management system to allow tracking and evaluation of products available from + various vendors. + + Attributes: + is_publicly_visible (bool): Indicates if the stock is publicly visible. Defaults to False. + vendor (ForeignKey): The vendor supplying this product stock. + price (float): The final price to the customer after markups. + product (ForeignKey): The product associated with this stock entry. + purchase_price (float): The price paid to the vendor for this product. + quantity (int): Available quantity of the product in stock. + sku (str): Vendor-assigned SKU for identifying the product. + digital_asset (FileField): Digital file associated with this stock if applicable. + """ + + is_publicly_visible = False + + vendor = ForeignKey( + "core.Vendor", + on_delete=CASCADE, + help_text=_("the vendor supplying this product stock"), + verbose_name=_("associated vendor"), + ) + price = FloatField( + default=0.0, + help_text=_("final price to the customer after markups"), + verbose_name=_("selling price"), + ) + product = ForeignKey( + "core.Product", + on_delete=CASCADE, + help_text=_("the product associated with this stock entry"), + verbose_name=_("associated product"), + related_name="stocks", + blank=True, + null=True, + ) + purchase_price = FloatField( + default=0.0, + help_text=_("the price paid to the vendor for this product"), + verbose_name=_("vendor purchase price"), + ) + quantity = IntegerField( + default=0, + help_text=_("available quantity of the product in stock"), + verbose_name=_("quantity in stock"), + ) + sku = CharField( + max_length=255, + help_text=_("vendor-assigned SKU for identifying the product"), + verbose_name=_("vendor sku"), + ) + digital_asset = FileField( + default=None, + blank=True, + null=True, + help_text=_("digital file associated with this stock if applicable"), + verbose_name=_("digital file"), + upload_to="downloadables/", + ) + + def __str__(self) -> str: + return f"{self.vendor.name} - {self.product!s}" + + class Meta: + verbose_name = _("stock") + verbose_name_plural = _("stock entries") + + +class Product(ExportModelOperationsMixin("product"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + 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. Designed for use in a + system that handles e-commerce or inventory management. + + This class interacts with related models (such as Category, Brand, and ProductTag) and + manages caching for frequently accessed properties to improve performance. It is used + to define and manipulate product data and its associated information within + an application. + + Attributes: + is_publicly_visible (bool): Indicates whether the product is visible to the public. + category (Category): The category this product belongs to. + brand (Brand, optional): Optionally associates this product with a brand. + tags (ProductTag): Tags that help describe or group this product. + is_digital (bool): Indicates whether this product is digitally delivered. + name (str): The identifying name for the product. + description (str, optional): A detailed description of the product. + partnumber (str): The unique part number for this product. + slug (str, optional): Auto-generated unique slug for the product. + + Meta: + verbose_name (str): The singular name of the product model. + verbose_name_plural (str): The plural name of the product model. + + Properties: + rating (float): The average rating of the product, rounded to 2 decimal places. + feedbacks_count (int): The total number of feedback entries associated with the product. + price (float): The lowest price of the product based on its stock, rounded to 2 decimal + places. + quantity (int): The total available quantity of the product across all its stocks. + total_orders (int): Counts the total orders made for the product in relevant statuses. + """ + is_publicly_visible = True - category: Category = ForeignKey( # type: ignore + category = ForeignKey( "core.Category", on_delete=CASCADE, help_text=_("category this product belongs to"), verbose_name=_("category"), related_name="products", ) - brand: Brand = ForeignKey( # type: ignore + brand = ForeignKey( "core.Brand", on_delete=CASCADE, blank=True, @@ -339,31 +632,31 @@ class Product(ExportModelOperationsMixin("product"), NiceModel): help_text=_("optionally associate this product with a brand"), verbose_name=_("brand"), ) - tags: ProductTag = ManyToManyField( # type: ignore + tags = ManyToManyField( "core.ProductTag", blank=True, help_text=_("tags that help describe or group this product"), verbose_name=_("product tags"), ) - is_digital: bool = BooleanField( # type: ignore + is_digital = BooleanField( default=False, help_text=_("indicates whether this product is digitally delivered"), verbose_name=_("is product digital"), blank=False, null=False, ) - name: str = CharField( # type: ignore + name = CharField( max_length=255, help_text=_("provide a clear identifying name for the product"), verbose_name=_("product name"), ) - description: str = TextField( # type: ignore + description = TextField( blank=True, null=True, help_text=_("add a detailed description of the product"), verbose_name=_("product description"), ) - partnumber: str = CharField( # type: ignore + partnumber = CharField( unique=True, default=None, blank=False, @@ -371,7 +664,7 @@ class Product(ExportModelOperationsMixin("product"), NiceModel): help_text=_("part number for this product"), verbose_name=_("part number"), ) - slug: str | None = AutoSlugField( # type: ignore + slug = AutoSlugField( populate_from=( "name", "brand__slug", @@ -414,15 +707,13 @@ class Product(ExportModelOperationsMixin("product"), NiceModel): cache_key = f"product_feedbacks_count_{self.pk}" feedbacks_count = cache.get(cache_key) if feedbacks_count is None: - feedbacks_count = Feedback.objects.filter( - order_product__product_id=self.pk - ).count() + feedbacks_count = Feedback.objects.filter(order_product__product_id=self.pk).count() cache.set(cache_key, feedbacks_count, 604800) return feedbacks_count @property - def price(self) -> float: - stock = self.stocks.order_by("price").only("price").first() + def price(self: Self) -> float: + stock = self.stocks.all().order_by("-price").only("price").first() price = stock.price if stock else 0.0 return round(price, 2) @@ -444,25 +735,55 @@ class Product(ExportModelOperationsMixin("product"), NiceModel): status__in=["FINISHED", "DELIVERING", "CREATED", "PAYMENT"], ).count() + @property + def personal_orders_only(self) -> bool: + return not self.quantity > 0 and self.price > 0.0 + + +class Attribute(ExportModelOperationsMixin("attribute"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents an attribute in the system. + + This class is used to define and manage attributes, which are customizable + pieces of data that can be associated with other entities. Attributes + have associated categories, groups, value types, and names. The model + supports multiple types of values, including string, integer, float, + boolean, array, and object. This allows for dynamic and flexible data + structuring. + + Attributes: + is_publicly_visible (bool): Denotes whether the attribute is publicly + visible. Defaults to True. + + categories (ManyToManyField): Categories to which this attribute + belongs. It is a many-to-many relationship with the `Category` model. + + group (ForeignKey): The group to which this attribute belongs. It is + a ForeignKey relation to the `AttributeGroup` model. + + value_type (CharField): The type of the attribute's value. Options + include string, integer, float, boolean, array, or object. + + name (CharField): The unique name of the attribute. + """ -class Attribute(ExportModelOperationsMixin("attribute"), NiceModel): is_publicly_visible = True - categories: Category = ManyToManyField( # type: ignore + categories = ManyToManyField( "core.Category", related_name="attributes", help_text=_("category of this attribute"), verbose_name=_("categories"), ) - group: AttributeGroup = ForeignKey( # type: ignore + group = ForeignKey( "core.AttributeGroup", on_delete=CASCADE, related_name="attributes", help_text=_("group of this attribute"), verbose_name=_("attribute group"), ) - value_type: str = CharField( # type: ignore + value_type = CharField( max_length=50, choices=[ ("string", _("string")), @@ -476,7 +797,7 @@ class Attribute(ExportModelOperationsMixin("attribute"), NiceModel): verbose_name=_("value type"), ) - name: str = CharField( # type: ignore + name = CharField( max_length=255, help_text=_("name of this attribute"), verbose_name=_("attribute's name"), @@ -491,17 +812,40 @@ class Attribute(ExportModelOperationsMixin("attribute"), NiceModel): verbose_name_plural = _("attributes") -class AttributeValue(ExportModelOperationsMixin("attribute_value"), NiceModel): +class AttributeValue(ExportModelOperationsMixin("attribute_value"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents a specific value for an attribute that is linked to a product. + + This class serves the purpose of mapping a value to an attribute for a + 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 - attribute: Attribute = ForeignKey( # type: ignore + attribute = ForeignKey( "core.Attribute", on_delete=CASCADE, related_name="values", help_text=_("attribute of this value"), verbose_name=_("attribute"), ) - product: Product = ForeignKey( # type: ignore + product = ForeignKey( "core.Product", on_delete=CASCADE, blank=False, @@ -510,7 +854,7 @@ class AttributeValue(ExportModelOperationsMixin("attribute_value"), NiceModel): verbose_name=_("associated product"), related_name="attributes", ) - value: str = TextField( # type: ignore + value = TextField( verbose_name=_("attribute value"), help_text=_("the specific value for this attribute"), ) @@ -523,10 +867,28 @@ class AttributeValue(ExportModelOperationsMixin("attribute_value"), NiceModel): verbose_name_plural = _("attribute values") -class ProductImage(ExportModelOperationsMixin("product_image"), NiceModel): +class ProductImage(ExportModelOperationsMixin("product_image"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents a product image associated with a product in the system. + + This class is designed to manage images for products, including functionality + for uploading image files, associating them with specific products, and + determining their display order. It also includes an accessibility feature + 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 - alt: str = CharField( # type: ignore + alt = CharField( max_length=255, help_text=_("provide alternative text for the image for accessibility"), verbose_name=_("image alt text"), @@ -536,13 +898,13 @@ class ProductImage(ExportModelOperationsMixin("product_image"), NiceModel): verbose_name=_("product image"), upload_to=get_product_uuid_as_path, ) - priority: int = IntegerField( # type: ignore + priority = IntegerField( default=1, validators=[MinValueValidator(1)], help_text=_("determines the order in which images are displayed"), verbose_name=_("display priority"), ) - product: ForeignKey = ForeignKey( + product = ForeignKey( "core.Product", on_delete=CASCADE, help_text=_("the product that this image represents"), @@ -562,27 +924,60 @@ class ProductImage(ExportModelOperationsMixin("product_image"), NiceModel): verbose_name_plural = _("product images") -class Promotion(ExportModelOperationsMixin("promotion"), NiceModel): +class Promotion(ExportModelOperationsMixin("promotion"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents a promotional campaign for products with a discount. + + This class is used to define and manage promotional campaigns that offer a + percentage-based discount for products. The class includes attributes for + setting the discount rate, providing details about the promotion, and linking + it to the applicable products. It integrates with the product catalog to + 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 - discount_percent: int = IntegerField( # type: ignore + discount_percent = IntegerField( validators=[MinValueValidator(1), MaxValueValidator(100)], help_text=_("percentage discount for the selected products"), verbose_name=_("discount percentage"), ) - name: str = CharField( # type: ignore + name = CharField( max_length=256, unique=True, help_text=_("provide a unique name for this promotion"), verbose_name=_("promotion name"), ) - description: str = TextField( # type: ignore + description = TextField( blank=True, null=True, help_text=_("add a detailed description of the product"), verbose_name=_("promotion description"), ) - products: ManyToManyField = ManyToManyField( # type: ignore + products = ManyToManyField( "core.Product", blank=True, help_text=_("select which products are included in this promotion"), @@ -599,71 +994,26 @@ class Promotion(ExportModelOperationsMixin("promotion"), NiceModel): return str(self.id) -class Stock(ExportModelOperationsMixin("stock"), NiceModel): +class Wishlist(ExportModelOperationsMixin("wishlist"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents a user's wishlist for storing and managing desired products. + + The Wishlist class provides functionality to manage a collection of products + that a user wishes to save. It supports operations such as adding products, + removing products, adding multiple products in bulk, and removing multiple + products in bulk. The wishlist is associated with a specific user and is + stored with optional public visibility status. + """ + is_publicly_visible = False - vendor: ForeignKey = ForeignKey( - "core.Vendor", - on_delete=CASCADE, - help_text=_("the vendor supplying this product stock"), - verbose_name=_("associated vendor"), - ) - price: float = FloatField( # type: ignore - default=0.0, - help_text=_("final price to the customer after markups"), - verbose_name=_("selling price"), - ) - product: ForeignKey = ForeignKey( # type: ignore - "core.Product", - on_delete=CASCADE, - help_text=_("the product associated with this stock entry"), - verbose_name=_("associated product"), - related_name="stocks", - blank=True, - null=True, - ) - purchase_price: float = FloatField( # type: ignore - default=0.0, - help_text=_("the price paid to the vendor for this product"), - verbose_name=_("vendor purchase price"), - ) - quantity: int = IntegerField( # type: ignore - default=0, - help_text=_("available quantity of the product in stock"), - verbose_name=_("quantity in stock"), - ) - sku: str = CharField( # type: ignore - max_length=255, - help_text=_("vendor-assigned SKU for identifying the product"), - verbose_name=_("vendor sku"), - ) - digital_asset = FileField( - default=None, - blank=True, - null=True, - help_text=_("digital file associated with this stock if applicable"), - verbose_name=_("digital file"), - upload_to="downloadables/", - ) - - def __str__(self) -> str: - return f"{self.vendor.name} - {self.product!s}" # type: ignore - - class Meta: - verbose_name = _("stock") - verbose_name_plural = _("stock entries") - - -class Wishlist(ExportModelOperationsMixin("wishlist"), NiceModel): - is_publicly_visible = False - - products: ManyToManyField = ManyToManyField( # type: ignore + products = ManyToManyField( "core.Product", blank=True, help_text=_("products that the user has marked as wanted"), verbose_name=_("wishlisted products"), ) - user: OneToOneField = OneToOneField( # type: ignore + user = OneToOneField( "vibes_auth.User", on_delete=CASCADE, blank=True, @@ -686,9 +1036,10 @@ class Wishlist(ExportModelOperationsMixin("wishlist"), NiceModel): if product in self.products.all(): return self self.products.add(product) - except Product.DoesNotExist: + except Product.DoesNotExist as dne: name = "Product" - raise Http404(_(f"{name} does not exist: {product_uuid}")) + uuid = product_uuid + raise Http404(_(f"{name} does not exist: {uuid}")) from dne return self @@ -698,9 +1049,10 @@ class Wishlist(ExportModelOperationsMixin("wishlist"), NiceModel): if product not in self.products.all(): return self self.products.remove(product) - except Product.DoesNotExist: + except Product.DoesNotExist as dne: name = "Product" - raise Http404(_(f"{name} does not exist: {product_uuid}")) + uuid = product_uuid + raise Http404(_(f"{name} does not exist: {uuid}")) from dne return self @@ -715,12 +1067,30 @@ class Wishlist(ExportModelOperationsMixin("wishlist"), NiceModel): return self -class Documentary(ExportModelOperationsMixin("attribute_group"), NiceModel): +class Documentary(ExportModelOperationsMixin("attribute_group"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Model representing a documentary record tied to a product. + + This class is used to store information about documentaries related to specific + products, including file uploads and their metadata. It contains methods and + properties to handle the file type and storage path for the documentary files. + 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 - product: ForeignKey = ForeignKey( - to=Product, on_delete=CASCADE, related_name="documentaries" - ) + product = ForeignKey(to=Product, on_delete=CASCADE, related_name="documentaries") document = FileField(upload_to=get_product_uuid_as_path) class Meta: @@ -738,23 +1108,60 @@ class Documentary(ExportModelOperationsMixin("attribute_group"), NiceModel): return self.document.name.split(".")[-1] or _("unresolved") -class Address(ExportModelOperationsMixin("address"), NiceModel): +class Address(ExportModelOperationsMixin("address"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents an address entity that includes location details and associations with + a user. Provides functionality for geographic and address data storage, as well + as integration with geocoding services. + + This class is designed to store detailed address information including components + 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 + 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 - address_line: str = TextField( # type: ignore + address_line = TextField( blank=True, null=True, help_text=_("address line for the customer"), verbose_name=_("address line"), ) - street: str = CharField(_("street"), max_length=255, null=True) # type: ignore - district: str = CharField(_("district"), max_length=255, null=True) # type: ignore - city: str = CharField(_("city"), max_length=100, null=True) # type: ignore - region: str = CharField(_("region"), max_length=100, null=True) # type: ignore - postal_code: str = CharField(_("postal code"), max_length=20, null=True) # type: ignore - country: str = CharField(_("country"), max_length=40, null=True) # type: ignore + street = CharField(_("street"), max_length=255, null=True) + district = CharField(_("district"), max_length=255, null=True) + city = CharField(_("city"), max_length=100, null=True) + region = CharField(_("region"), max_length=100, null=True) + postal_code = CharField(_("postal code"), max_length=20, null=True) + country = CharField(_("country"), max_length=40, null=True) - location: PointField = PointField( # type: ignore + location: PointField = PointField( geography=True, srid=4326, null=True, @@ -762,15 +1169,15 @@ class Address(ExportModelOperationsMixin("address"), NiceModel): help_text=_("geolocation point: (longitude, latitude)"), ) - raw_data: dict = JSONField(blank=True, null=True, help_text=_("full JSON response from geocoder for this address")) # type: ignore + raw_data = JSONField(blank=True, null=True, help_text=_("full JSON response from geocoder for this address")) - api_response: dict = JSONField( # type: ignore + api_response = JSONField( blank=True, null=True, help_text=_("stored JSON response from the geocoding service"), ) - user: ForeignKey = ForeignKey(to="vibes_auth.User", on_delete=CASCADE, blank=True, null=True) # type: ignore + user = ForeignKey(to="vibes_auth.User", on_delete=CASCADE, blank=True, null=True) objects = AddressManager() @@ -786,17 +1193,45 @@ class Address(ExportModelOperationsMixin("address"), NiceModel): return f"{base} for {self.user.email}" if self.user else base -class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel): +class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents a promotional code that can be used for discounts, managing its validity, + type of discount, and application. + + The PromoCode class stores details about a promotional code, including its unique + identifier, discount properties (amount or percentage), validity period, associated + 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. + + 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 - code: str = CharField( # type: ignore + code = CharField( max_length=20, unique=True, default=get_random_code, help_text=_("unique code used by a user to redeem a discount"), verbose_name=_("promo code identifier"), ) - discount_amount: Decimal = DecimalField( # type: ignore + discount_amount = DecimalField( max_digits=10, decimal_places=2, blank=True, @@ -804,32 +1239,32 @@ class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel): help_text=_("fixed discount amount applied if percent is not used"), verbose_name=_("fixed discount amount"), ) - discount_percent: int = IntegerField( # type: ignore + discount_percent = IntegerField( validators=[MinValueValidator(1), MaxValueValidator(100)], blank=True, null=True, help_text=_("percentage discount applied if fixed amount is not used"), verbose_name=_("percentage discount"), ) - end_time: datetime = DateTimeField( # type: ignore + end_time = DateTimeField( blank=True, null=True, help_text=_("timestamp when the promocode expires"), verbose_name=_("end validity time"), ) - start_time: datetime = DateTimeField( # type: ignore + start_time = DateTimeField( blank=True, null=True, help_text=_("timestamp from which this promocode is valid"), verbose_name=_("start validity time"), ) - used_on: datetime = DateTimeField( # type: ignore + used_on = DateTimeField( blank=True, null=True, help_text=_("timestamp when the promocode was used, blank if not used yet"), verbose_name=_("usage timestamp"), ) - user: ForeignKey = ForeignKey( # type: ignore + user = ForeignKey( "vibes_auth.User", on_delete=CASCADE, help_text=_("user assigned to this promocode if applicable"), @@ -848,9 +1283,7 @@ class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel): self.discount_amount is None and self.discount_percent is None ): 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) @@ -863,36 +1296,55 @@ class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel): return "amount" return "percent" - def use(self, order: "Order") -> float: + def use(self, order) -> float: if self.used_on: raise ValueError(_("promocode already used")) - amount = order.total_price + if not order.attributes: + order.attributes = {} + + promo_amount = order.total_price if self.discount_type == "percent": - amount -= round(amount * (self.discount_percent / 100), 2) - order.attributes.update( - {"promocode": str(self.uuid), "final_price": amount} - ) + promo_amount -= round(promo_amount * (float(self.discount_percent) / 100), 2) # type: ignore [arg-type] + order.attributes.update({"promocode_uuid": str(self.uuid), "final_price": promo_amount}) order.save() elif self.discount_type == "amount": - amount -= round(float(self.discount_amount), 2) - order.attributes.update( - {"promocode": str(self.uuid), "final_price": amount} - ) + promo_amount -= round(float(self.discount_amount), 2) # type: ignore [arg-type] + order.attributes.update({"promocode_uuid": str(self.uuid), "final_price": promo_amount}) order.save() else: raise ValueError(_(f"invalid discount type for promocode {self.uuid}")) self.used_on = datetime.datetime.now() self.save() - return amount + return promo_amount -class Order(ExportModelOperationsMixin("order"), NiceModel): +class Order(ExportModelOperationsMixin("order"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents an order placed by a user. + + This class models an order within the application, including its various attributes such as billing + and shipping information, status, associated user, notifications, and related operations. + Orders can have associated products, promotions can be applied, addresses set, and shipping or billing + details updated. Equally, functionality supports managing the products in the order lifecycle. + + Attributes: + billing_address (Address): The billing address used for the order. + promo_code (PromoCode): An optional promo code applied to the order. + shipping_address (Address): The shipping address used for the order. + status (str): The current status of the order (e.g., PENDING, COMPLETED). + notifications (dict): JSON structure dictating notifications for the user. + attributes (dict): JSON representation of additional order-specific attributes. + user (User): The user who placed the order. + buy_time (datetime): Timestamp when the order was finalized. + human_readable_id (str): A unique human-readable identifier for the order. + """ + is_publicly_visible = False - billing_address: Address = ForeignKey( # type: ignore + billing_address = ForeignKey( "core.Address", on_delete=CASCADE, blank=True, @@ -901,7 +1353,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): help_text=_("the billing address used for this order"), verbose_name=_("billing address"), ) - promo_code: PromoCode = ForeignKey( # type: ignore + promo_code = ForeignKey( "core.PromoCode", on_delete=PROTECT, blank=True, @@ -909,7 +1361,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): help_text=_("optional promo code applied to this order"), verbose_name=_("applied promo code"), ) - shipping_address: Address = ForeignKey( # type: ignore + shipping_address = ForeignKey( "core.Address", on_delete=CASCADE, blank=True, @@ -918,26 +1370,26 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): help_text=_("the shipping address used for this order"), verbose_name=_("shipping address"), ) - status: str = CharField( # type: ignore + status = CharField( default="PENDING", max_length=64, choices=ORDER_STATUS_CHOICES, help_text=_("current status of the order in its lifecycle"), verbose_name=_("order status"), ) - notifications: dict = JSONField( # type: ignore + notifications = JSONField( blank=True, null=True, help_text=_("json structure of notifications to display to users"), verbose_name=_("notifications"), ) - attributes: dict = JSONField( # type: ignore + attributes = JSONField( blank=True, null=True, help_text=_("json representation of order attributes for this order"), verbose_name=_("attributes"), ) - user = ForeignKey( # type: ignore + user = ForeignKey( "vibes_auth.User", on_delete=CASCADE, help_text=_("the user who placed the order"), @@ -946,14 +1398,14 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): blank=True, null=True, ) - buy_time: datetime = DateTimeField( # type: ignore + buy_time = DateTimeField( help_text=_("the timestamp when the order was finalized"), verbose_name=_("buy time"), default=None, null=True, blank=True, ) - human_readable_id: str = CharField( # type: ignore + human_readable_id = CharField( max_length=8, help_text=_("a human-readable identifier for the order"), verbose_name=_("human readable id"), @@ -966,13 +1418,15 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): verbose_name_plural = _("orders") def __str__(self) -> str: - return f"#{self.pk} for {self.user.email if self.user else 'unregistered user'}" # type: ignore + return f"#{self.pk} for {self.user.email if self.user else 'unregistered user'}" @property def is_business(self) -> bool: - return self.attributes.get("is_business", False) if self.attributes else False + return (self.attributes.get("is_business", False) if self.attributes else False) or ( + self.user.attributes.get("is_business", False) if self.user else False + ) - def save(self, **kwargs): + def save(self, **kwargs: dict) -> Self: pending_orders = 0 if self.user: pending_orders = self.user.orders.filter(status="PENDING").count() @@ -987,8 +1441,7 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): sum( ( order_product.buy_price * order_product.quantity - if order_product.status not in FAILED_STATUSES - and order_product.buy_price is not None + if order_product.status not in FAILED_STATUSES and order_product.buy_price is not None else 0.0 ) for order_product in self.order_products.all() @@ -1004,17 +1457,15 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): def add_product( self, - product_uuid: str | None = None, + product_uuid=None, attributes: list | None = None, - update_quantity: bool = True, + update_quantity=True, ): if attributes is None: attributes = [] if self.status not in ["PENDING", "MOMENTAL"]: - raise ValueError( - _("you cannot add products to an order that is not a pending one") - ) + raise ValueError(_("you cannot add products to an order that is not a pending one")) try: product = Product.objects.get(uuid=product_uuid) @@ -1023,12 +1474,10 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): buy_price = product.price - promotions = Promotion.objects.filter( - is_active=True, products__in=[product] - ).order_by("discount_percent") + promotions = Promotion.objects.filter(is_active=True, products__in=[product]).order_by("discount_percent") if promotions.exists(): - buy_price -= round(product.price * (promotions.first().discount_percent / 100), 2) # type: ignore + buy_price -= round(product.price * (promotions.first().discount_percent / 100), 2) # type: ignore [union-attr] order_product, is_created = OrderProduct.objects.get_or_create( product=product, @@ -1038,32 +1487,29 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): ) if not is_created and update_quantity: if product.quantity < order_product.quantity + 1: - raise BadRequest( - _("you cannot add more products than available in stock") - ) + raise BadRequest(_("you cannot add more products than available in stock")) order_product.quantity += 1 order_product.buy_price = product.price order_product.save() return self - except Product.DoesNotExist: + except Product.DoesNotExist as dne: name = "Product" - raise Http404(_(f"{name} does not exist: {product_uuid}")) + uuid = product_uuid + raise Http404(_(f"{name} does not exist: {uuid}")) from dne def remove_product( self, - product_uuid: str | None = None, - attributes: dict | None = None, - zero_quantity: bool = False, + product_uuid=None, + attributes=None, + zero_quantity=False, ): if attributes is None: attributes = {} if self.status not in ["PENDING", "MOMENTAL"]: - raise ValueError( - _("you cannot remove products from an order that is not a pending one") - ) + raise ValueError(_("you cannot remove products from an order that is not a pending one")) try: product = Product.objects.get(uuid=product_uuid) order_product = self.order_products.get(product=product, order=self) @@ -1077,66 +1523,52 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): order_product.quantity -= 1 order_product.save() return self - except Product.DoesNotExist: + except Product.DoesNotExist as dne: name = "Product" - raise Http404(_(f"{name} does not exist: {product_uuid}")) - except OrderProduct.DoesNotExist: + uuid = product_uuid + raise Http404(_(f"{name} does not exist: {uuid}")) from dne + except OrderProduct.DoesNotExist as dne: name = "OrderProduct" - query = ( - f"product: {product_uuid}, order: {self.uuid}, attributes: {attributes}" - ) - raise Http404(_(f"{name} does not exist with query <{query}>")) + query = f"product: {product_uuid}, order: {self.uuid}, attributes: {attributes}" + raise Http404(_(f"{name} does not exist with query <{query}>")) from dne def remove_all_products(self): if self.status not in ["PENDING", "MOMENTAL"]: - raise ValueError( - _("you cannot remove products from an order that is not a pending one") - ) + raise ValueError(_("you cannot remove products from an order that is not a pending one")) for order_product in self.order_products.all(): self.order_products.remove(order_product) order_product.delete() return self - def remove_products_of_a_kind(self, product_uuid: str): + def remove_products_of_a_kind(self, product_uuid): if self.status not in ["PENDING", "MOMENTAL"]: - raise ValueError( - _("you cannot remove products from an order that is not a pending one") - ) + raise ValueError(_("you cannot remove products from an order that is not a pending one")) try: product = Product.objects.get(uuid=product_uuid) order_product = self.order_products.get(product=product, order=self) self.order_products.remove(order_product) order_product.delete() - except Product.DoesNotExist: + except Product.DoesNotExist as dne: name = "Product" - raise Http404(_(f"{name} does not exist: {product_uuid}")) + uuid = product_uuid + raise Http404(_(f"{name} does not exist: {uuid}")) from dne return self @property def is_whole_digital(self): - return ( - self.order_products.count() - == self.order_products.filter(product__is_digital=True).count() - ) + return self.order_products.count() == self.order_products.filter(product__is_digital=True).count() - def apply_promocode(self, promocode_uuid: str): + def apply_promocode(self, promocode_uuid): try: - promocode: PromoCode = PromoCode.objects.get(uuid=promocode_uuid) - except PromoCode.DoesNotExist: - raise Http404(_("promocode does not exist")) + promocode = PromoCode.objects.get(uuid=promocode_uuid) + except PromoCode.DoesNotExist as dne: + raise Http404(_("promocode does not exist")) from dne return promocode.use(self) - def apply_addresses(self, billing_address_uuid, shipping_address_uuid): + def apply_addresses(self, billing_address_uuid: str | None = None, shipping_address_uuid: str | None = None): try: - if not any([shipping_address_uuid, billing_address_uuid]): - if self.is_whole_digital: - return - else: - raise ValueError( - _( - "you can only buy physical products with shipping address specified" - ) - ) + if not any([shipping_address_uuid, billing_address_uuid]) and not self.is_whole_digital: + raise ValueError(_("you can only buy physical products with shipping address specified")) if billing_address_uuid and not shipping_address_uuid: shipping_address = Address.objects.get(uuid=billing_address_uuid) @@ -1154,8 +1586,8 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): self.shipping_address = shipping_address self.save() - except Address.DoesNotExist: - raise Http404(_("address does not exist")) + except Address.DoesNotExist as dne: + raise Http404(_("address does not exist")) from dne def buy( self, @@ -1164,20 +1596,27 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): promocode_uuid: str | None = None, billing_address: str | None = None, shipping_address: str | None = None, + chosen_products: list | None = None, ) -> Self | Transaction | None: - if config.DISABLED_COMMERCE: - raise DisabledCommerceError( - _("you can not buy at this moment, please try again in a few minutes") - ) + order = self - if (not force_balance and not force_payment) or ( - force_balance and force_payment - ): + if not self.attributes: + self.attributes = {} + + if chosen_products: + order = Order.objects.create(status="MOMENTAL", user=self.user) + order.bulk_add_products(chosen_products, update_quantity=True) + + if config.DISABLED_COMMERCE: + raise DisabledCommerceError(_("you can not buy at this moment, please try again in a few minutes")) + + if (not force_balance and not force_payment) or (force_balance and force_payment): raise ValueError(_("invalid force value")) - self.apply_addresses(billing_address, shipping_address) + if any([billing_address, shipping_address]): + order.apply_addresses(billing_address, shipping_address) - if self.total_quantity < 1: + if order.total_quantity < 1: raise ValueError(_("you cannot purchase an empty order!")) force = None @@ -1188,40 +1627,46 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): if force_payment: force = "payment" - amount = ( - self.apply_promocode(promocode_uuid) if promocode_uuid else self.total_price - ) + amount = self.attributes.get("final_amount") or order.total_price + + if self.attributes.get("promocode_uuid") and not self.attributes.get("final_amount"): + amount = order.apply_promocode(self.attributes.get("promocode_uuid")) + + if promocode_uuid and not self.attributes.get("final_amount"): + amount = order.apply_promocode(promocode_uuid) + + if not order.user: + raise ValueError(_("you cannot buy an order without a user")) + + if not order.user.payments_balance: + raise ValueError(_("a user without a balance cannot buy with balance")) match force: case "balance": - if self.user.payments_balance.amount < amount: # type: ignore - raise NotEnoughMoneyError( - _("insufficient funds to complete the order") - ) - self.status = "CREATED" - self.buy_time = timezone.now() - self.order_products.all().update(status="DELIVERING") - self.save() - return self + if order.user.payments_balance.amount < amount: + raise NotEnoughMoneyError(_("insufficient funds to complete the order")) + with transaction.atomic(): + order.status = "CREATED" + order.buy_time = timezone.now() + order.update_order_products_statuses("DELIVERING") + order.save() + return order case "payment": - self.status = "PAYMENT" - self.save() + order.status = "PAYMENT" + order.buy_time = timezone.now() + order.save() return Transaction.objects.create( - balance=self.user.payments_balance, # type: ignore + balance=order.user.payments_balance, amount=amount, currency=CURRENCY_CODE, - order=self, + order=order, ) - return self + return order - def buy_without_registration( - self, products: list, promocode_uuid: str, **kwargs - ) -> Transaction | None: + def buy_without_registration(self, products: list, promocode_uuid, **kwargs) -> Transaction | None: if config.DISABLED_COMMERCE: - raise DisabledCommerceError( - _("you can not buy at this moment, please try again in a few minutes") - ) + raise DisabledCommerceError(_("you can not buy at this moment, please try again in a few minutes")) if len(products) < 1: raise ValueError(_("you cannot purchase an empty order!")) @@ -1242,25 +1687,17 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): available_payment_methods = cache.get("payment_methods").get("payment_methods") if payment_method not in available_payment_methods: - raise ValueError( - _( - f"invalid payment method: {payment_method} from {available_payment_methods}" - ) - ) + raise ValueError(_(f"invalid payment method: {payment_method} from {available_payment_methods}")) billing_customer_address_uuid = kwargs.get("billing_customer_address") shipping_customer_address_uuid = kwargs.get("shipping_customer_address") - self.apply_addresses( - billing_customer_address_uuid, shipping_customer_address_uuid - ) + self.apply_addresses(billing_customer_address_uuid, shipping_customer_address_uuid) for product_uuid in products: self.add_product(product_uuid) - amount = ( - self.apply_promocode(promocode_uuid) if promocode_uuid else self.total_price - ) + amount = self.apply_promocode(promocode_uuid) if promocode_uuid else self.total_price self.status = "CREATED" @@ -1301,53 +1738,79 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): self.status = "FINISHED" self.save() - def bulk_add_products(self, products: list): + def update_order_products_statuses(self, status: str = "PENDING"): + self.order_products.update(status=status) + + def bulk_add_products(self, products: list[dict[str, Any]], update_quantity: bool = False): for product in products: self.add_product( - product.get("uuid"), + product.get("uuid") or product.get("product_uuid"), attributes=product.get("attributes"), - update_quantity=False, + update_quantity=update_quantity, ) return self def bulk_remove_products(self, products: list): for product in products: self.remove_product( - product.get("uuid"), + product.get("uuid") or product.get("product_uuid"), attributes=product.get("attributes"), zero_quantity=True, ) return self -class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel): +class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents a product associated with 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 + 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 + 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 + 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 - buy_price: float = FloatField( # type: ignore + buy_price = FloatField( blank=True, null=True, help_text=_("the price paid by the customer for this product at purchase time"), verbose_name=_("purchase price at order time"), ) - comments: str = TextField( # type: ignore + comments = TextField( blank=True, null=True, help_text=_("internal comments for admins about this ordered product"), verbose_name=_("internal comments"), ) - notifications: dict = JSONField( # type: ignore + notifications = JSONField( blank=True, null=True, help_text=_("json structure of notifications to display to users"), verbose_name=_("user notifications"), ) - attributes: dict = JSONField( # type: ignore + attributes = JSONField( blank=True, null=True, help_text=_("json representation of this item's attributes"), verbose_name=_("ordered product attributes"), ) - order: Order = ForeignKey( # type: ignore + order = ForeignKey( "core.Order", on_delete=CASCADE, help_text=_("reference to the parent order that contains this product"), @@ -1355,7 +1818,7 @@ class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel): related_name="order_products", null=True, ) - product: Product = ForeignKey( # type: ignore + product = ForeignKey( "core.Product", on_delete=PROTECT, blank=True, @@ -1363,14 +1826,14 @@ class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel): help_text=_("the specific product associated with this order line"), verbose_name=_("associated product"), ) - quantity: int = PositiveIntegerField( # type: ignore + quantity = PositiveIntegerField( blank=False, null=False, default=1, help_text=_("quantity of this specific product in the order"), verbose_name=_("product quantity"), ) - status: str = CharField( # type: ignore + status = CharField( max_length=128, blank=False, null=False, @@ -1381,7 +1844,10 @@ class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel): ) def __str__(self) -> str: - return f"{self.product.name} for ({self.order.user.email if self.order.user else 'unregistered user'})" # type: ignore + return ( + f"{self.product.name if self.product else self.uuid}" + f" for ({self.order.user.email if self.order and self.order.user else 'unregistered user'})" + ) class Meta: verbose_name = _("order product") @@ -1405,9 +1871,7 @@ class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel): "errors": [ { "detail": ( - error - if error - else f"Something went wrong with {self.uuid} for some reason..." + error if error else f"Something went wrong with {self.uuid} for some reason..." ) }, ] @@ -1423,40 +1887,61 @@ class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel): return self @property - def total_price(self) -> float: - return round(self.buy_price * self.quantity, 2) + def total_price(self: Self) -> float: + return round(float(self.buy_price) * self.quantity, 2) # type: ignore [arg-type] @property - def download_url(self) -> str: - if self.product.is_digital and self.product.stocks.first().digital_asset: # type: ignore - return self.download.url + def download_url(self: Self) -> str: + if self.product and self.product.stocks: + if self.product.is_digital and self.product.stocks.first().digital_asset: # type: ignore [union-attr] + return self.download.url return "" - def do_feedback( - self, rating: int = 10, comment: str = "", action: str = "add" - ) -> Optional["Feedback"]: + def do_feedback(self, rating=10, comment="", action="add") -> Optional["Feedback"]: + if not self.order: + raise ValueError(_("order product must have an order")) if action not in ["add", "remove"]: raise ValueError(_(f"wrong action specified for feedback: {action}")) if action == "remove" and self.feedback: self.feedback.delete() return None if action == "add" and not self.feedback: - if self.order.status not in ["MOMENTAL", "PENDING"]: # type: ignore - return Feedback.objects.create( - rating=rating, comment=comment, order_product=self - ) + if self.order.status not in ["MOMENTAL", "PENDING"]: + return Feedback.objects.create(rating=rating, comment=comment, order_product=self) else: - raise ValueError( - _("you cannot feedback an order which is not received") - ) + raise ValueError(_("you cannot feedback an order which is not received")) return None -class DigitalAssetDownload(ExportModelOperationsMixin("attribute_group"), NiceModel): +class DigitalAssetDownload(ExportModelOperationsMixin("attribute_group"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Represents the downloading functionality for digital assets associated + with orders. + + The DigitalAssetDownload class provides the ability to manage and access + downloads related to order products. It maintains information about the + associated order product, the number of downloads, and whether the asset + 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 - order_product: OneToOneField = OneToOneField(to=OrderProduct, on_delete=CASCADE, related_name="download") # type: ignore - num_downloads: int = IntegerField(default=0) # type: ignore + order_product = OneToOneField(to=OrderProduct, on_delete=CASCADE, related_name="download") + num_downloads = IntegerField(default=0) class Meta: verbose_name = _("download") @@ -1468,33 +1953,48 @@ class DigitalAssetDownload(ExportModelOperationsMixin("attribute_group"), NiceMo @property def url(self): if self.order_product.status != "FINISHED": - raise ValueError( - _("you can not download a digital asset for a non-finished order") - ) + raise ValueError(_("you can not download a digital asset for a non-finished order")) - return f"https://api.{config.BASE_DOMAIN}/download/{urlsafe_base64_encode(force_bytes(self.order_product.uuid))}" + return ( + f"https://api.{config.BASE_DOMAIN}/download/{urlsafe_base64_encode(force_bytes(self.order_product.uuid))}" + ) -class Feedback(ExportModelOperationsMixin("feedback"), NiceModel): +class Feedback(ExportModelOperationsMixin("feedback"), NiceModel): # type: ignore [misc, django-manager-missing] + """ + Manages user feedback for 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, + 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. + + 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 - comment: str = TextField( # type: ignore + comment = TextField( blank=True, null=True, help_text=_("user-provided comments about their experience with the product"), verbose_name=_("feedback comments"), ) - order_product: OrderProduct = OneToOneField( # type: ignore + order_product = OneToOneField( "core.OrderProduct", on_delete=CASCADE, blank=False, null=False, - help_text=_( - "references the specific product in an order that this feedback is about" - ), + help_text=_("references the specific product in an order that this feedback is about"), verbose_name=_("related order product"), ) - rating: float = FloatField( # type: ignore + rating = FloatField( blank=True, null=True, help_text=_("user-assigned rating for the product"), @@ -1503,8 +2003,27 @@ class Feedback(ExportModelOperationsMixin("feedback"), NiceModel): ) def __str__(self) -> str: - return f"{self.rating} by {self.order_product.order.user.email}" + if self.order_product and self.order_product.order and self.order_product.order.user: + return f"{self.rating} by {self.order_product.order.user.email}" + return f"{self.rating} | {self.uuid}" class Meta: verbose_name = _("feedback") verbose_name_plural = _("feedbacks") + + +class SeoMeta(NiceModel): + uuid = None + content_type = ForeignKey(ContentType, on_delete=CASCADE) + object_id = UUIDField() + content_object = GenericForeignKey("content_type", "object_id") + + meta_title = CharField(max_length=70, blank=True) + meta_description = CharField(max_length=180, blank=True) + canonical_override = URLField(blank=True) + robots = CharField(max_length=40, blank=True, default="index,follow") + social_image = ImageField(upload_to="seo/", blank=True, null=True) + extras = JSONField(blank=True, null=True) + + class Meta: + unique_together = ("content_type", "object_id") diff --git a/core/permissions.py b/core/permissions.py index a462229b..ff1f9c92 100644 --- a/core/permissions.py +++ b/core/permissions.py @@ -47,6 +47,9 @@ class EvibesPermission(permissions.BasePermission): app_label = model._meta.app_label model_name = model._meta.model_name + if view.additional.get(action) == "ALLOW": + return True + if action == "create" and view.additional.get("create") == "ALLOW": return True diff --git a/core/serializers/detail.py b/core/serializers/detail.py index 1869140b..8feceb33 100644 --- a/core/serializers/detail.py +++ b/core/serializers/detail.py @@ -1,13 +1,12 @@ import logging -from collections.abc import Collection +from collections import defaultdict from contextlib import suppress -from typing import Any +from typing import Collection, Any from django.contrib.auth.models import AnonymousUser from django.core.cache import cache from django.db.models.functions import Length from rest_framework.fields import JSONField, SerializerMethodField -from rest_framework.request import Request from rest_framework.serializers import ModelSerializer from rest_framework_recursive.fields import RecursiveField @@ -31,9 +30,8 @@ from core.models import ( ) from core.serializers.simple import CategorySimpleSerializer, ProductSimpleSerializer from core.serializers.utility import AddressSerializer -from vibes_auth.models import User -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") class AttributeGroupDetailSerializer(ModelSerializer): @@ -76,42 +74,46 @@ class CategoryDetailSerializer(ModelSerializer): return None def get_filterable_attributes(self, obj: Category) -> list[dict]: - filterable_results = cache.get(f"{obj.uuid}_filterable_results", []) - + cache_key = f"{obj.uuid}_filterable_results" + filterable_results = cache.get(cache_key) if filterable_results: return filterable_results - request: Request | None = self.context.get("request") - user: User | AnonymousUser | None = getattr(request, "user") # noqa: B009 + request = self.context.get("request") + user = getattr(request, "user", AnonymousUser()) + attrs_qs = obj.attributes.all() if user.has_perm("view_attribute") else obj.attributes.filter(is_active=True) + attributes = list(attrs_qs) - if user is None: - user = AnonymousUser() - - attributes = obj.attributes.all() if user.has_perm("view_attribute") else obj.attributes.filter(is_active=True) - - for attr in attributes: - distinct_vals = ( - AttributeValue.objects.annotate(value_length=Length("value")) - .filter(attribute=attr, product__category=obj, value_length__lte=30) - .values_list("value", flat=True) - .distinct() + attr_ids = [a.id for a in attributes] + raw_vals = ( + AttributeValue.objects.annotate(value_length=Length("value")) + .filter( + attribute_id__in=attr_ids, + product__category=obj, + value_length__lte=30, ) + .values_list("attribute_id", "value") + .distinct() + ) - distinct_vals_list = list(distinct_vals)[0:128] if len(list(distinct_vals)) > 128 else list(distinct_vals) + grouped = defaultdict(list) + for attr_id, val in raw_vals: + grouped[attr_id].append(val) + filterable_results = [] + for attr in attributes: + vals = grouped.get(attr.id, []) + slice_vals = vals[:128] if len(vals) > 128 else vals filterable_results.append( { "attribute_name": attr.name, - "possible_values": distinct_vals_list, + "possible_values": slice_vals, "value_type": attr.value_type, } ) - if user is None: - user = AnonymousUser() - if not user.has_perm("view_attribute"): - cache.set(f"{obj.uuid}_filterable_results", filterable_results, 86400) + cache.set(cache_key, filterable_results, 86400) return filterable_results @@ -122,14 +124,7 @@ class CategoryDetailSerializer(ModelSerializer): else: children = obj.children.filter(is_active=True) - if obj.children.exists(): - return ( - CategoryDetailSerializer(children, many=True, context=self.context).data - if obj.children.exists() - else [] - ) - else: - return [] + return CategoryDetailSerializer(children, many=True, context=self.context).data if obj.children.exists() else [] class BrandDetailSerializer(ModelSerializer): diff --git a/core/serializers/seo.py b/core/serializers/seo.py new file mode 100644 index 00000000..780d25a5 --- /dev/null +++ b/core/serializers/seo.py @@ -0,0 +1,13 @@ +from rest_framework.fields import CharField, DictField, ListField +from rest_framework.serializers import Serializer + + +class SeoSnapshotSerializer(Serializer): + title = CharField() + description = CharField() + canonical = CharField() + robots = CharField() + hreflang = ListField(child=DictField(), required=False) + open_graph = DictField() + twitter = DictField() + json_ld = ListField(child=DictField()) diff --git a/core/serializers/simple.py b/core/serializers/simple.py index f05e1a75..658f5fe4 100644 --- a/core/serializers/simple.py +++ b/core/serializers/simple.py @@ -1,5 +1,5 @@ -from collections.abc import Collection from contextlib import suppress +from typing import Collection, Any from rest_framework.fields import JSONField, SerializerMethodField from rest_framework.relations import PrimaryKeyRelatedField @@ -27,8 +27,8 @@ from core.serializers.utility import AddressSerializer class AttributeGroupSimpleSerializer(ModelSerializer): - parent: PrimaryKeyRelatedField = PrimaryKeyRelatedField(read_only=True) # type: ignore - children: PrimaryKeyRelatedField = PrimaryKeyRelatedField(many=True, read_only=True) # type: ignore + parent = PrimaryKeyRelatedField(read_only=True) # type: ignore [assignment, var-annotated] + children = PrimaryKeyRelatedField(many=True, read_only=True) # type: ignore [assignment, var-annotated] class Meta: model = AttributeGroup @@ -59,21 +59,14 @@ class CategorySimpleSerializer(ModelSerializer): return obj.image.url return None - def get_children(self, obj) -> Collection: + def get_children(self, obj) -> Collection[Any]: request = self.context.get("request") if request is not None and request.user.has_perm("view_category"): children = obj.children.all() else: children = obj.children.filter(is_active=True) - if obj.children.exists(): - return ( - CategorySimpleSerializer(children, many=True, context=self.context).data - if obj.children.exists() - else [] - ) - else: - return [] + return CategorySimpleSerializer(children, many=True, context=self.context).data if obj.children.exists() else [] class BrandSimpleSerializer(ModelSerializer): @@ -163,6 +156,7 @@ class ProductSimpleSerializer(ModelSerializer): price = SerializerMethodField() quantity = SerializerMethodField() feedbacks_count = SerializerMethodField() + personal_orders_only = SerializerMethodField() class Meta: model = Product @@ -175,6 +169,7 @@ class ProductSimpleSerializer(ModelSerializer): "partnumber", "brand", "feedbacks_count", + "personal_orders_only", "category", "tags", "images", @@ -196,6 +191,9 @@ class ProductSimpleSerializer(ModelSerializer): def get_quantity(self, obj: Product) -> int: return obj.quantity + def get_personal_orders_only(self, obj: Product) -> bool: + return obj.personal_orders_only + class VendorSimpleSerializer(ModelSerializer): class Meta: diff --git a/core/serializers/utility.py b/core/serializers/utility.py index 0fc2437e..8ecd124a 100644 --- a/core/serializers/utility.py +++ b/core/serializers/utility.py @@ -89,7 +89,7 @@ class DoFeedbackSerializer(Serializer): class CacheOperatorSerializer(Serializer): key = CharField(required=True) - data = JSONField(required=False) # type: ignore + data = JSONField(required=False) # type: ignore [assignment] timeout = IntegerField(required=False) @@ -122,7 +122,7 @@ class RecursiveField(Field): class AddOrderProductSerializer(Serializer): product_uuid = CharField(required=True) - attributes = JSONField(required=False, default=dict) + attributes = ListField(required=False, child=DictField(), default=list) class BulkAddOrderProductsSerializer(Serializer): @@ -160,6 +160,7 @@ class BuyOrderSerializer(Serializer): promocode_uuid = CharField(required=False) shipping_address_uuid = CharField(required=False) billing_address_uuid = CharField(required=False) + chosen_products = ListField(child=AddOrderProductSerializer(), required=False) class BuyUnregisteredOrderSerializer(Serializer): diff --git a/core/signals.py b/core/signals.py index adeb3035..c58c20d6 100644 --- a/core/signals.py +++ b/core/signals.py @@ -10,7 +10,8 @@ from django.utils.timezone import now from django.utils.translation import gettext_lazy as _ from sentry_sdk import capture_exception -from core.models import Category, Order, Product, PromoCode, Wishlist +from core.models import Category, Order, Product, PromoCode, Wishlist, DigitalAssetDownload +from core.serializers import OrderProductSimpleSerializer from core.utils import ( generate_human_readable_id, resolve_translations_for_elasticsearch, @@ -19,7 +20,7 @@ from core.utils.emailing import send_order_created_email, send_order_finished_em from evibes.utils.misc import create_object from vibes_auth.models import User -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") @receiver(post_save, sender=User) @@ -64,6 +65,9 @@ def create_promocode_on_user_referring(instance, created, **_kwargs): @receiver(post_save, sender=Order) def process_order_changes(instance, created, **_kwargs): + if type(instance.attributes) is not dict: + instance.attributes = {} + if not created: if instance.status != "PENDING" and instance.user: pending_orders = Order.objects.filter(user=instance.user, status="PENDING") @@ -85,14 +89,25 @@ def process_order_changes(instance, created, **_kwargs): break if instance.status in ["CREATED", "PAYMENT"]: + logger.debug( + "Processing order changes: %s\nWith orderproducts: %s", + str(instance.__dict__), + str(OrderProductSimpleSerializer(instance.order_products.all(), many=True).data), + ) if not instance.is_whole_digital: send_order_created_email.delay(instance.uuid) - for order_product in instance.order_products.filter(status="DELIVERING"): - if not order_product.product.is_digital: + for order_product in instance.order_products.filter(status="DELIVERING", product__is_digital=True): + if order_product.product.stocks.filter(digital_asset__isnull=False).exists(): + order_product.status = "FINISHED" + download = DigitalAssetDownload.objects.create(order_product=order_product) + order_product.download = download + order_product.save() + order_product.order.user.payments_balance.amount -= order_product.buy_price + order_product.order.user.payments_balance.save() continue - try: + logger.debug("Trying to buy: %s", str(order_product.uuid)) vendor_name = ( order_product.product.stocks.filter(price=order_product.buy_price).first().vendor.name.lower() ) @@ -111,7 +126,9 @@ def process_order_changes(instance, created, **_kwargs): instance.status = "FAILED" instance.save() - if instance.status == "FINISHED": + if instance.status == "FINISHED" and not instance.attributes.get("system_email_sent", False): + instance.attributes["system_email_sent"] = True + instance.save() send_order_finished_email.delay(instance.uuid) diff --git a/core/sitemaps.py b/core/sitemaps.py index 0f9a629a..a3d79c09 100644 --- a/core/sitemaps.py +++ b/core/sitemaps.py @@ -1,5 +1,4 @@ from django.contrib.sitemaps import Sitemap -from django.utils.text import slugify from core.models import Brand, Category, Product from evibes.settings import LANGUAGE_CODE @@ -9,7 +8,7 @@ class ProductSitemap(Sitemap): protocol = "https" changefreq = "daily" priority = 0.9 - limit = 40000 + limit = 25000 def items(self): return ( @@ -17,6 +16,8 @@ class ProductSitemap(Sitemap): is_active=True, brand__is_active=True, category__is_active=True, + stocks__isnull=False, + stocks__vendor__is_active=True, ) .only("uuid", "name", "modified", "slug") .order_by("-modified") @@ -33,7 +34,7 @@ class CategorySitemap(Sitemap): protocol = "https" changefreq = "weekly" priority = 0.7 - limit = 40000 + limit = 10000 def items(self): return Category.objects.filter(is_active=True).only("uuid", "name", "modified").order_by("-modified") @@ -42,15 +43,14 @@ class CategorySitemap(Sitemap): return obj.modified def location(self, obj): - slug = slugify(obj.name) - return f"/{LANGUAGE_CODE}/catalog/{obj.uuid}/{slug}" + return f"/{LANGUAGE_CODE}/catalog/{obj.slug}" class BrandSitemap(Sitemap): protocol = "https" changefreq = "weekly" priority = 0.6 - limit = 40000 + limit = 10000 def items(self): return Brand.objects.filter(is_active=True).only("uuid", "name", "modified").order_by("-modified") @@ -59,5 +59,4 @@ class BrandSitemap(Sitemap): return obj.modified def location(self, obj): - slug = slugify(obj.name) - return f"/{LANGUAGE_CODE}/brand/{obj.uuid}/{slug}" + return f"/{LANGUAGE_CODE}/brand/{obj.slug}" diff --git a/core/tasks.py b/core/tasks.py index 3bbe5f33..39faaca7 100644 --- a/core/tasks.py +++ b/core/tasks.py @@ -13,14 +13,14 @@ from django.core.cache import cache from core.models import Product, Promotion from core.utils.caching import set_default_cache -from core.vendors import delete_stale +from core.vendors import delete_stale, VendorInactiveError from evibes.settings import MEDIA_ROOT logger = get_task_logger(__name__) -@shared_task -def update_products_task(): +@shared_task(queue="stock_updater") +def update_products_task() -> tuple[bool, str]: """ Run a background task to update product data and manage stale products. @@ -44,6 +44,8 @@ def update_products_task(): vendor = vendor_class() try: vendor.update_stock() + except VendorInactiveError: + logger.info(f"Skipping {vendor_class} due to inactivity") except Exception as e: logger.warning(f"Skipping {vendor_class} due to error: {e!s}") @@ -54,8 +56,8 @@ def update_products_task(): return True, "Success" -@shared_task -def update_orderproducts_task(): +@shared_task(queue="default") +def update_orderproducts_task() -> tuple[bool, str]: """ Updates the statuses of order products for all vendors listed in the `vendors_classes`. Each vendor class in the `vendors_classes` list is @@ -76,8 +78,8 @@ def update_orderproducts_task(): return True, "Success" -@shared_task -def set_default_caches_task(): +@shared_task(queue="default") +def set_default_caches_task() -> tuple[bool, str]: """ Task to set default caches in the application's memory. @@ -92,8 +94,8 @@ def set_default_caches_task(): return True, "Success" -@shared_task -def remove_stale_product_images(): +@shared_task(queue="default") +def remove_stale_product_images() -> tuple[bool, str] | None: """ Removes stale product images from the products directory by identifying directories whose names do not match any UUIDs currently present in the database. @@ -139,7 +141,7 @@ def remove_stale_product_images(): logger.error("Error removing directory %s: %s", entry_path, e) -@shared_task +@shared_task(queue="default") def process_promotions() -> tuple[bool, str]: """ Processes and updates promotions based on holiday data or default settings. diff --git a/core/templates/digital_order_created_email.html b/core/templates/digital_order_created_email.html index 45bb1f59..06d6e388 100644 --- a/core/templates/digital_order_created_email.html +++ b/core/templates/digital_order_created_email.html @@ -91,7 +91,7 @@ diff --git a/core/templates/digital_order_delivered_email.html b/core/templates/digital_order_delivered_email.html index 7b2df364..fbf27cbc 100644 --- a/core/templates/digital_order_delivered_email.html +++ b/core/templates/digital_order_delivered_email.html @@ -1,5 +1,4 @@ {% load tz static i18n filters conditions %} - @@ -91,7 +90,7 @@ diff --git a/core/templates/shipped_order_created_email.html b/core/templates/shipped_order_created_email.html index 722b7a53..0346a0a7 100644 --- a/core/templates/shipped_order_created_email.html +++ b/core/templates/shipped_order_created_email.html @@ -91,7 +91,7 @@ diff --git a/core/templates/shipped_order_delivered_email.html b/core/templates/shipped_order_delivered_email.html index 722b7a53..0346a0a7 100644 --- a/core/templates/shipped_order_delivered_email.html +++ b/core/templates/shipped_order_delivered_email.html @@ -91,7 +91,7 @@ diff --git a/core/utils/__init__.py b/core/utils/__init__.py index a1013daf..53d1f447 100644 --- a/core/utils/__init__.py +++ b/core/utils/__init__.py @@ -4,68 +4,116 @@ import secrets from contextlib import contextmanager from constance import config +from django.conf import settings from django.core.cache import cache from django.db import transaction from django.utils.crypto import get_random_string +from django.utils.translation import get_language from evibes.settings import DEBUG, EXPOSABLE_KEYS, LANGUAGE_CODE -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") + + +def graphene_current_lang(): + """ + Determines the currently active language code. + + This function retrieves the current language from the available language + settings. If no language is set, it defaults to the application's default + language code. The language code is returned in lowercase. + + Returns: + str: The currently active language code in lowercase. + """ + return (get_language() or settings.LANGUAGE_CODE).lower() + + +def graphene_abs(request, path_or_url: str) -> str: + """ + Builds and returns an absolute URI for a given path or URL. + + Summary: + This function takes a relative path or URL and constructs a fully + qualified absolute URI using the request object. + + Args: + request: The request object used to build the absolute URI. + path_or_url: str + The relative path or URL to be converted to an absolute URI. + + Returns: + str: The absolute URI corresponding to the provided path or URL. + """ + return request.build_absolute_uri(path_or_url) def get_random_code() -> str: """ - Generates a random string of a specified length. This method calls the - get_random_string function to create a random alphanumeric string of - 20 characters in length. + Generates a random alphanumeric string of a fixed length. - Returns - ------- - str - A 20-character-long alphanumeric string. + This function uses a utility function to generate a random string + consisting of letters and digits. The length of the string is fixed + to 20 characters. The generated string can be used for purposes + such as unique identifiers or tokens. + + Returns: + str: Randomly generated alphanumeric string of length 20. """ return get_random_string(20) -def get_product_uuid_as_path(instance, filename): +def get_product_uuid_as_path(instance, filename: str = "") -> str: """ - Generates a unique file path for a product using its UUID. + Generates a file path for a product using its UUID. - This function constructs a file path that includes the product UUID - in its directory structure. The path format is "products/{product_uuid}/{filename}", - where `product_uuid` is derived from the instance's product attribute, and - `filename` corresponds to the original name of the file being processed. + 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. - Parameters: - instance: Object - The model instance containing the product attribute with the desired UUID. - filename: str - The original name of the file for which the path is being generated. + 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 representing the generated unique file path that adheres to the - format "products/{product_uuid}/{filename}". + str: A string that represents the constructed file path. """ return "products" + "/" + str(instance.product.uuid) + "/" + filename -def get_brand_name_as_path(instance, filename): +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 @contextmanager def atomic_if_not_debug(): """ - A context manager to execute a database operation within an atomic transaction - when the `DEBUG` setting is disabled. If `DEBUG` is enabled, it bypasses - transactional behavior. This allows safe rollback in production and easier - debugging in development. + Context manager to wrap a block of code in an atomic transaction if the DEBUG + setting is not enabled. - Yields - ------ - None - Yields control to the enclosed block of code. + This context manager ensures that the code block executes within an atomic + database transaction, preventing partial updates to the database in case of + an exception. If the DEBUG setting is enabled, no transaction is enforced, + allowing for easier debugging. + + Yields: + None: This context manager does not return any values. """ if not DEBUG: with transaction.atomic(): @@ -76,21 +124,37 @@ def atomic_if_not_debug(): def is_url_safe(url: str) -> bool: """ - Determine if a given URL is safe. This function evaluates whether - the provided URL starts with "https://", making it a potentially - secure resource by evaluating its prefix using a regular expression. + Determines if a given URL starts with "https://" indicating it is a secure URL. - Arguments: - url (str): The URL to evaluate. + 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://", indicating it may - be considered safe. False otherwise. + bool: True if the URL starts with "https://", False otherwise. """ return bool(re.match(r"^https://", url, re.IGNORECASE)) -def format_attributes(attributes: str | None = None): +def format_attributes(attributes: str | None = None) -> dict: + """ + Parses a string of attributes into a dictionary. + + This function takes a string input representing attributes and their values, + 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. + 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: return {} @@ -110,7 +174,18 @@ def format_attributes(attributes: str | None = None): return result -def get_project_parameters(): +def get_project_parameters() -> dict: + """ + Fetches project parameters from cache or configuration. + + This function retrieves project parameters from a cache if available. + If they are not cached, it collects the parameters from a designated + configuration source, formats their keys to lowercase, and then stores + them in the cache for a limited period. + + Returns: + dict: A dictionary containing the project parameters with lowercase keys. + """ parameters = cache.get("parameters", {}) if not parameters: @@ -122,7 +197,20 @@ def get_project_parameters(): return parameters -def resolve_translations_for_elasticsearch(instance, field_name): +def resolve_translations_for_elasticsearch(instance, field_name) -> None: + """ + Resolves translations for a given field in an Elasticsearch-compatible + format. It checks if the localized version of the field contains data, + 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}", "") filled_field = getattr(instance, field_name, "") if not field: @@ -134,12 +222,18 @@ CROCKFORD = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789" def generate_human_readable_id(length: int = 6) -> str: """ - Generate a human-readable ID of `length` characters (from the Crockford set), - with a single hyphen inserted: - - 50% chance at the exact middle - - 50% chance at a random position between characters (1 to length-1) + Generates a human-readable identifier using Crockford's Base32 characters. - The final string length will be `length + 1` (including the hyphen). + This function creates a string of a specified length composed of randomly + selected characters from the Crockford Base32 alphabet. A dash is inserted + at a random or mid-point position in the identifier for better readability. + + Parameters: + length (int): The length of the identifier excluding the dash. Must be + greater than 0. Default is 6. + + Returns: + str: A human-readable identifier with the specified length plus a dash. """ chars = [secrets.choice(CROCKFORD) for _ in range(length)] @@ -147,3 +241,17 @@ def generate_human_readable_id(length: int = 6) -> str: chars.insert(pos, "-") return "".join(chars) + + +def generate_human_readable_token() -> str: + """ + Generates a human-readable token. + + This function creates a random token using characters from + the CROCKFORD base32 set. The generated token is 20 characters + long and is designed to be human-readable. + + Returns: + str: A 20-character random token. + """ + return "".join([secrets.choice(CROCKFORD) for _ in range(20)]) diff --git a/core/utils/caching.py b/core/utils/caching.py index c912c788..6071e154 100644 --- a/core/utils/caching.py +++ b/core/utils/caching.py @@ -9,7 +9,7 @@ from django.utils.translation import gettext_lazy as _ from evibes.settings import UNSAFE_CACHE_KEYS from vibes_auth.models import User -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") def is_safe_cache_key(key: str): diff --git a/core/utils/db.py b/core/utils/db.py index 3cca4558..601ee56d 100644 --- a/core/utils/db.py +++ b/core/utils/db.py @@ -1,22 +1,10 @@ import logging -from django.db.models import Model from django.db.models.constants import LOOKUP_SEP -from django.utils.translation import gettext_lazy as _ from django_extensions.db.fields import AutoSlugField from slugify import slugify -logger = logging.getLogger(__name__) - - -def list_to_queryset(model: Model, data: list): - if not isinstance(model, Model): - raise ValueError(_(f"{model} must be model")) - if not isinstance(data, list): - raise ValueError(_(f"{data} must be list object")) - - pk_list = [obj.pk for obj in data] - return model.objects.filter(pk__in=pk_list) +logger = logging.getLogger("django") def unicode_slugify_function(content): diff --git a/core/utils/emailing.py b/core/utils/emailing.py index 750dd6e3..c262bf50 100644 --- a/core/utils/emailing.py +++ b/core/utils/emailing.py @@ -12,7 +12,7 @@ from core.models import Order, OrderProduct from core.utils.constance import set_email_settings -@shared_task +@shared_task(queue="default") def contact_us_email(contact_info): set_email_settings() connection = mail.get_connection() @@ -30,7 +30,7 @@ def contact_us_email(contact_info): "config": config, }, ), - to=[config.EMAIL_HOST_USER], + to=[config.EMAIL_FROM], from_email=f"{config.PROJECT_NAME} <{config.EMAIL_FROM}>", connection=connection, ) @@ -40,14 +40,17 @@ def contact_us_email(contact_info): return True, str(contact_info.get("email")) -@shared_task +@shared_task(queue="default") def send_order_created_email(order_pk: str) -> tuple[bool, str]: try: order = Order.objects.get(pk=order_pk) except Order.DoesNotExist: return False, f"Order not found with the given pk: {order_pk}" - activate(order.user.language) # type: ignore + if not order.user: + return False, f"Order's user not found with the given pk: {order_pk}" + + activate(order.user.language) set_email_settings() connection = mail.get_connection() @@ -64,7 +67,7 @@ def send_order_created_email(order_pk: str) -> tuple[bool, str]: "total_price": order.total_price, }, ), - to=[order.user.email], # type: ignore + to=[order.user.email], from_email=f"{config.PROJECT_NAME} <{config.EMAIL_FROM}>", connection=connection, ) @@ -74,13 +77,16 @@ def send_order_created_email(order_pk: str) -> tuple[bool, str]: return True, str(order.uuid) -@shared_task +@shared_task(queue="default") def send_order_finished_email(order_pk: str) -> tuple[bool, str]: def send_digital_assets_email(ops: list[OrderProduct]): if len(ops) <= 0: return - activate(order.user.language) # type: ignore + if not order.user: + return + + activate(order.user.language) set_email_settings() connection = mail.get_connection() @@ -91,16 +97,16 @@ def send_order_finished_email(order_pk: str) -> tuple[bool, str]: template_name="digital_order_delivered_email.html", context={ "order_uuid": order.human_readable_id, - "user_first_name": order.user.first_name, # type: ignore + "user_first_name": "" or order.user.first_name, "order_products": ops, "project_name": config.PROJECT_NAME, "contact_email": config.EMAIL_FROM, - "total_price": round(sum(op.buy_price for op in ops), 2), - "display_system_attributes": order.user.has_perm("core.view_order"), # type: ignore + "total_price": round(sum(0.0 or op.buy_price for op in ops), 2), # type: ignore [misc] + "display_system_attributes": order.user.has_perm("core.view_order"), "today": datetime.today(), }, ), - to=[order.user.email], # type: ignore + to=[order.user.email], from_email=f"{config.PROJECT_NAME} <{config.EMAIL_FROM}>", connection=connection, ) @@ -110,7 +116,9 @@ def send_order_finished_email(order_pk: str) -> tuple[bool, str]: def send_thank_you_email(ops: list[OrderProduct]): if ops: pass - activate(order.user.language) # type: ignore + if not order.user: + return + activate(order.user.language) set_email_settings() @@ -121,6 +129,9 @@ def send_order_finished_email(order_pk: str) -> tuple[bool, str]: except Order.DoesNotExist: return False, f"Order not found with the given pk: {order_pk}" + if not order.user: + return False, f"Order's user not found with the given pk: {order_pk}" + digital_ops = [] for digital_op in order.order_products.filter( diff --git a/core/utils/seo_builders.py b/core/utils/seo_builders.py new file mode 100644 index 00000000..93c51470 --- /dev/null +++ b/core/utils/seo_builders.py @@ -0,0 +1,98 @@ +from constance import config +from django.conf import settings + + +def org_schema(): + return { + "@context": "https://schema.org", + "@type": "Organization", + "name": config.COMPANY_NAME, + "url": f"https://{config.BASE_DOMAIN}/", + "logo": f"https://{config.BASE_DOMAIN}/static/logo.png", + } + + +def website_schema(): + return { + "@context": "https://schema.org", + "@type": "WebSite", + "name": config.PROJECT_NAME, + "url": f"https://{config.BASE_DOMAIN}/", + "potentialAction": { + "@type": "SearchAction", + "target": f"https://{config.BASE_DOMAIN}/search?q={{query}}", + "query-input": "required name=query", + }, + } + + +def breadcrumb_schema(items): + return { + "@context": "https://schema.org", + "@type": "BreadcrumbList", + "itemListElement": [ + {"@type": "ListItem", "position": i + 1, "name": name, "item": url} for i, (name, url) in enumerate(items) + ], + } + + +def item_list_schema(urls): + return { + "@context": "https://schema.org", + "@type": "ItemList", + "itemListElement": [{"@type": "ListItem", "position": i + 1, "url": u} for i, u in enumerate(urls)], + } + + +def product_schema(product, images, rating=None): + offers = [] + for stock in product.stocks.all(): + offers.append( + { + "@type": "Offer", + "price": round(stock.price, 2), + "priceCurrency": settings.CURRENCY_CODE, + "availability": "https://schema.org/InStock" if stock.quantity > 0 else "https://schema.org/OutOfStock", + "sku": stock.sku, + "url": f"https://{config.BASE_DOMAIN}/product/{product.slug}", + } + ) + data = { + "@context": "https://schema.org", + "@type": "Product", + "name": product.name, + "description": product.description or "", + "sku": product.partnumber or "", + "brand": {"@type": "Brand", "name": product.brand.name} if product.brand else None, + "image": [img.image.url for img in images] or [], + "offers": offers[:1] if offers else None, + } + if rating and rating["count"] > 0: + data["aggregateRating"] = { + "@type": "AggregateRating", + "ratingValue": rating["value"], + "reviewCount": rating["count"], + } + return {k: v for k, v in data.items() if v not in (None, [], {})} + + +def category_schema(category, url): + return { + "@context": "https://schema.org", + "@type": "CollectionPage", + "name": category.name, + "description": category.description or "", + "url": url, + } + + +def brand_schema(brand, url, logo_url=None): + data = { + "@context": "https://schema.org", + "@type": "Brand", + "name": brand.name, + "url": url, + } + if logo_url: + data["logo"] = logo_url + return data diff --git a/core/vendors/__init__.py b/core/vendors/__init__.py index 216c03b6..781a5b40 100644 --- a/core/vendors/__init__.py +++ b/core/vendors/__init__.py @@ -1,9 +1,11 @@ import json from contextlib import suppress +from decimal import Decimal from math import ceil, log10 from typing import Any -from django.db import IntegrityError +from django.db import IntegrityError, transaction +from django.db.models import QuerySet from core.elasticsearch import process_query from core.models import ( @@ -13,6 +15,7 @@ from core.models import ( Brand, Category, Product, + ProductImage, Stock, Vendor, ) @@ -56,6 +59,10 @@ class VendorError(Exception): pass +class VendorInactiveError(VendorError): + pass + + class AbstractVendor: """ Abstract class defining vendor-related operations and handling. @@ -72,13 +79,15 @@ class AbstractVendor: instance. """ - def __init__(self, vendor_name=None, currency="USD"): + def __init__(self, vendor_name: str | None = None, currency: str = "USD") -> None: self.vendor_name = vendor_name self.currency = currency - self.blocked_attributes = [] + self.blocked_attributes: list[Any] = [] @staticmethod - def chunk_data(data, num_chunks=20): + def chunk_data(data: list[Any] | None = None, num_chunks: int = 20) -> list[list[Any]] | list[Any]: + if not data: + return [] total = len(data) if total == 0: return [] @@ -86,7 +95,7 @@ class AbstractVendor: return [data[i : i + chunk_size] for i in range(0, total, chunk_size)] @staticmethod - def auto_convert_value(value: Any): + def auto_convert_value(value: Any) -> tuple[Any, str]: """ Attempts to convert a value to a more specific type. Handles booleans, numbers, objects (dicts), and arrays (lists), @@ -145,9 +154,11 @@ class AbstractVendor: return value, "string" @staticmethod - def auto_resolver_helper(model: Brand | Category, resolving_name: str) -> Brand | Category | None: + def auto_resolver_helper(model: type[Brand] | type[Category], resolving_name: str) -> Brand | Category | None: queryset = model.objects.filter(name=resolving_name) if not queryset.exists(): + if len(resolving_name) > 255: + resolving_name = resolving_name[:255] return model.objects.get_or_create(name=resolving_name, defaults={"is_active": False})[0] elif queryset.filter(is_active=True).count() > 1: queryset = queryset.filter(is_active=True) @@ -160,7 +171,7 @@ class AbstractVendor: queryset.delete() return chosen - def auto_resolve_category(self, category_name: str): + def auto_resolve_category(self, category_name: str = "") -> Category | None: if category_name: try: search = process_query(category_name) @@ -176,9 +187,9 @@ class AbstractVendor: except Category.DoesNotExist: pass - return self.auto_resolver_helper(Category, category_name) # type: ignore + return self.auto_resolver_helper(Category, category_name) - def auto_resolve_brand(self, brand_name: str): + def auto_resolve_brand(self, brand_name: str = "") -> Brand | None: if brand_name: try: search = process_query(brand_name) @@ -194,7 +205,7 @@ class AbstractVendor: except Brand.DoesNotExist: pass - return self.auto_resolver_helper(Brand, brand_name) # type: ignore + return self.auto_resolver_helper(Brand, brand_name) def resolve_price( self, @@ -211,13 +222,13 @@ class AbstractVendor: price = float(original_price) if category and category.markup_percent: - price *= 1 + float(category.markup_percent) / 100.0 # type: ignore + price *= 1 + float(category.markup_percent) / 100.0 elif vendor and vendor.markup_percent: price *= 1 + vendor.markup_percent / 100.0 return round(price, 2) - def resolve_price_with_currency(self, price, provider, currency=None): + def resolve_price_with_currency(self, price: float | int | Decimal, provider: str, currency: str = "") -> float: rates = get_rates(provider) rate = rates.get(currency or self.currency) @@ -225,7 +236,7 @@ class AbstractVendor: if not rate: raise RatesError(f"No rate found for {currency or self.currency} in {rates} with probider {provider}...") - return round(price / rate, 2) if rate else round(price, 2) + return float(round(price / rate, 2)) if rate else float(round(price, 2)) @staticmethod def round_price_marketologically(price: float) -> float: @@ -260,41 +271,96 @@ class AbstractVendor: return float(psychological) - def get_vendor_instance(self): + def get_vendor_instance(self) -> Vendor | None: try: vendor = Vendor.objects.get(name=self.vendor_name) if vendor.is_active: return vendor - raise VendorError(f"Vendor {self.vendor_name!r} is inactive...") - except Vendor.DoesNotExist: - raise Exception(f"No matching vendor found with name {self.vendor_name!r}...") + raise VendorInactiveError(f"Vendor {self.vendor_name!r} is inactive...") + except Vendor.DoesNotExist as dne: + raise Exception(f"No matching vendor found with name {self.vendor_name!r}...") from dne - def get_products(self): + def get_products(self) -> None: pass - def get_products_queryset(self): + def get_products_queryset(self) -> QuerySet[Product] | None: 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] | None: 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] | None: return AttributeValue.objects.filter( product__in=self.get_products_queryset(), product__orderproduct__isnull=True ) - def prepare_for_stock_update(self): - self.get_products_queryset().update(is_active=False) + def prepare_for_stock_update(self, method: str = "deactivate") -> None: + products = self.get_products_queryset() + if products is None: + return - def delete_inactives(self): - self.get_products_queryset().filter(is_active=False).delete() + # noinspection PyUnreachableCode + match method: + case "deactivate": + products.update(is_active=False) + case "delete": + products.delete() + case "description": + products.update(description="EVIBES_DELETED_PRODUCT") + case _: + raise ValueError(f"Invalid method {method!r} for products update...") - def delete_belongings(self): - self.get_products_queryset().delete() - self.get_stocks_queryset().delete() - self.get_attribute_values_queryset().delete() + def delete_inactives(self, inactivation_method: str = "deactivate", size: int = 5000) -> None: + match inactivation_method: + case "deactivate": + filter_kwargs: dict[str, Any] = {"is_active": False} + case "description": + filter_kwargs: dict[str, Any] = {"description__exact": "EVIBES_DELETED_PRODUCT"} + case _: + raise ValueError(f"Invalid method {inactivation_method!r} for products cleaner...") - def process_attribute(self, key: str, value, product: Product, attr_group: AttributeGroup): + while True: + products = self.get_products_queryset() + + if products is None: + return + + batch_ids = list(products.filter(**filter_kwargs).values_list("pk", flat=True)[:size]) + if not batch_ids: + break + with suppress(Exception): + AttributeValue.objects.filter(product_id__in=batch_ids).delete() + ProductImage.objects.filter(product_id__in=batch_ids).delete() + Product.objects.filter(pk__in=batch_ids).delete() + + def delete_belongings(self) -> None: + self.get_products_queryset().delete() # type: ignore [union-attr] + self.get_stocks_queryset().delete() # type: ignore [union-attr] + self.get_attribute_values_queryset().delete() # type: ignore [union-attr] + + def get_or_create_attribute_safe(self, *, name: str, attr_group: AttributeGroup) -> Attribute: + key = name[:255] + try: + attr = Attribute.objects.get(name=key) + except Attribute.DoesNotExist: + try: + with transaction.atomic(): + attr = Attribute.objects.create( + name=key, + group=attr_group, + is_active=True, + value_type="string", + ) + except IntegrityError: + attr = Attribute.objects.get(name=key) + + if not attr.is_active: + attr.is_active = True + attr.save(update_fields=["is_active"]) + + return attr + + def process_attribute(self, key: str, value: Any, product: Product, attr_group: AttributeGroup) -> None: if not value: return @@ -308,6 +374,9 @@ class AbstractVendor: is_created = False + if len(key) > 255: + key = key[:255] + try: attribute, is_created = Attribute.objects.get_or_create( name=key, @@ -316,15 +385,15 @@ class AbstractVendor: defaults={"is_active": True}, ) except Attribute.MultipleObjectsReturned: - attribute = Attribute.objects.filter(name=key, group=attr_group).order_by("uuid").first() # type: ignore + attribute = Attribute.objects.filter(name=key, group=attr_group).order_by("uuid").first() # type: ignore [assignment] attribute.is_active = True attribute.value_type = attr_value_type - attribute.save() + attribute.save() # type: ignore [no-untyped-call] except IntegrityError: return attribute.categories.add(product.category) - attribute.save() + attribute.save() # type: ignore [no-untyped-call] if not is_created: return @@ -336,12 +405,12 @@ class AbstractVendor: defaults={"is_active": True}, ) - def update_stock(self): + def update_stock(self) -> None: pass - def update_order_products_statuses(self): + def update_order_products_statuses(self) -> None: pass -def delete_stale(): +def delete_stale() -> None: Product.objects.filter(stocks__isnull=True, orderproduct__isnull=True).delete() diff --git a/core/views.py b/core/views.py index 8315af07..a3b28f30 100644 --- a/core/views.py +++ b/core/views.py @@ -1,5 +1,7 @@ +import logging import mimetypes import os +import traceback import requests from django.contrib.sitemaps.views import index as _sitemap_index_view @@ -8,9 +10,10 @@ from django.core.cache import cache from django.core.exceptions import BadRequest from django.http import FileResponse, Http404, JsonResponse from django.shortcuts import redirect -from django.utils.encoding import force_str from django.utils.http import urlsafe_base64_decode from django.utils.translation import gettext_lazy as _ +from django.views.decorators.cache import cache_page +from django.views.decorators.vary import vary_on_headers from django_ratelimit.decorators import ratelimit from djangorestframework_camel_case.render import CamelCaseJSONRenderer from djangorestframework_camel_case.util import camelize @@ -51,25 +54,80 @@ from evibes import settings from evibes.settings import LANGUAGES from payments.serializers import TransactionProcessSerializer +logger = logging.getLogger("django") + +@cache_page(60 * 60 * 12) +@vary_on_headers("Host") 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["Content-Type"] = "application/xml; charset=utf-8" return response +@cache_page(60 * 60 * 24) +@vary_on_headers("Host") 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["Content-Type"] = "application/xml; charset=utf-8" return response 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): return request 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): # noinspection PyUnresolvedReferences context = super().get_context_data(**kwargs) @@ -78,6 +136,16 @@ class CustomSwaggerView(SpectacularSwaggerView): 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): # noinspection PyUnresolvedReferences context = super().get_context_data(**kwargs) @@ -87,6 +155,25 @@ class CustomRedocView(SpectacularRedocView): @extend_schema_view(**LANGUAGE_SCHEMA) class SupportedLanguagesView(APIView): + """ + 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 permission_classes = [ AllowAny, @@ -117,6 +204,31 @@ class SupportedLanguagesView(APIView): @extend_schema_view(**PARAMETERS_SCHEMA) class WebsiteParametersView(APIView): + """ + 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 permission_classes = [ AllowAny, @@ -134,6 +246,25 @@ class WebsiteParametersView(APIView): @extend_schema_view(**CACHE_SCHEMA) class CacheOperatorView(APIView): + """ + 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 permission_classes = [ AllowAny, @@ -159,6 +290,23 @@ class CacheOperatorView(APIView): @extend_schema_view(**CONTACT_US_SCHEMA) class ContactUsView(APIView): + """ + 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 renderer_classes = [ CamelCaseJSONRenderer, @@ -178,6 +326,21 @@ class ContactUsView(APIView): @extend_schema_view(**REQUEST_CURSED_URL_SCHEMA) class RequestCursedURLView(APIView): + """ + 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 = [ AllowAny, ] @@ -217,8 +380,21 @@ class RequestCursedURLView(APIView): @extend_schema_view(**SEARCH_SCHEMA) class GlobalSearchView(APIView): """ - A global search endpoint. - It returns a response grouping matched items by index. + 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 = [ @@ -234,6 +410,23 @@ class GlobalSearchView(APIView): @extend_schema_view(**BUY_AS_BUSINESS_SCHEMA) class BuyAsBusinessView(APIView): + """ + 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. + """ + @ratelimit(key="ip", rate="2/h", block=True) def post(self, request, *_args, **kwargs): serializer = BuyAsBusinessOrderSerializer(data=request.data) @@ -258,8 +451,29 @@ class BuyAsBusinessView(APIView): def download_digital_asset_view(request, *args, **kwargs): + """ + 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: - uuid = force_str(urlsafe_base64_decode(kwargs["encoded_uuid"])) + logger.debug(f"download_digital_asset_view: {kwargs}") + uuid = urlsafe_base64_decode(str(kwargs.get("order_product_uuid"))).decode("utf-8") + download = DigitalAssetDownload.objects.get(order_product__uuid=uuid) if download.num_downloads >= 1: @@ -268,39 +482,76 @@ def download_digital_asset_view(request, *args, **kwargs): download.num_downloads += 1 download.save() - file_path = download.order_product.product.stocks.first().digital_asset.file.path + file_path = download.order_product.product.stocks.first().digital_asset.path content_type, encoding = mimetypes.guess_type(file_path) if not content_type: content_type = "application/octet-stream" - with open(file_path, "rb") as file: - response = FileResponse(file, content_type=content_type) - filename = os.path.basename(file_path) - response["Content-Disposition"] = f'attachment; filename="{filename}"' - return response + response = FileResponse(open(file_path, "rb"), content_type=content_type) + filename = os.path.basename(file_path) + response["Content-Disposition"] = f'attachment; filename="{filename}"' + return response except BadRequest as e: - return JsonResponse({"error": str(e)}, status=400) + return JsonResponse(camelize({"error": str(e)}), status=400) except DigitalAssetDownload.DoesNotExist: - return JsonResponse({"error": "Digital asset not found"}, status=404) + return JsonResponse(camelize({"error": "Digital asset not found"}), status=404) except Exception as e: capture_exception(e) return JsonResponse( - {"error": "An error occurred while trying to download the digital asset"}, + camelize( + { + "error": "An error occurred while trying to download the digital asset", + "traceback": traceback.format_exc() if settings.DEBUG else None, + "received": {"order_product_uuid": kwargs.get("order_product_uuid", "")}, + } + ), status=500, ) def favicon_view(request, *args, **kwargs): + """ + Handles requests for the favicon of a website. 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. + + 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: + 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: favicon_path = os.path.join(settings.BASE_DIR, "static/favicon.png") return FileResponse(open(favicon_path, "rb"), content_type="image/x-icon") - except FileNotFoundError: - raise Http404(_("favicon not found")) + except FileNotFoundError as fnfe: + raise Http404(_("favicon not found")) from fnfe def index(request, *args, **kwargs): + """ + 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. + + Args: + 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") diff --git a/core/viewsets.py b/core/viewsets.py index ee3db6ad..69250806 100644 --- a/core/viewsets.py +++ b/core/viewsets.py @@ -2,7 +2,9 @@ import logging import uuid from uuid import UUID -from django.db.models import Q, QuerySet +from constance import config +from django.conf import settings +from django.db.models import Q, Prefetch from django.http import Http404 from django.shortcuts import get_object_or_404 from django.utils.decorators import method_decorator @@ -14,6 +16,7 @@ from drf_spectacular.utils import extend_schema_view from rest_framework import status from rest_framework.decorators import action from rest_framework.exceptions import PermissionDenied +from rest_framework.permissions import AllowAny from rest_framework.renderers import MultiPartRenderer from rest_framework.response import Response from rest_framework.viewsets import ModelViewSet @@ -101,16 +104,47 @@ from core.serializers import ( WishlistDetailSerializer, WishlistSimpleSerializer, ) +from core.serializers.seo import SeoSnapshotSerializer from core.utils import format_attributes from core.utils.messages import permission_denied_message from core.utils.nominatim import fetch_address_suggestions +from core.utils.seo_builders import ( + org_schema, + website_schema, + breadcrumb_schema, + product_schema, + category_schema, + item_list_schema, + brand_schema, +) from evibes.settings import DEBUG from payments.serializers import TransactionProcessSerializer -logger = logging.getLogger("django.request") +logger = logging.getLogger("django") class EvibesViewSet(ModelViewSet): + """ + Defines a viewset for managing Evibes-related operations. + + The EvibesViewSet class inherits from ModelViewSet and provides functionality + for handling actions and operations on Evibes entities. It includes support + for dynamic serializer classes based on the current action, customizable + permissions, and rendering formats. + + Attributes: + action_serializer_classes: Dictionary mapping action names to their specific + serializer classes. + additional: Dictionary to hold additional data related to the view. + permission_classes: List of permission classes applicable to this viewset. + renderer_classes: List of renderer classes supported for response formatting. + + Methods: + get_serializer_class(self): + Returns the serializer class for the current action or the default + serializer class from the parent ModelViewSet. + """ + action_serializer_classes: dict = {} additional: dict = {} permission_classes = [EvibesPermission] @@ -122,6 +156,27 @@ class EvibesViewSet(ModelViewSet): @extend_schema_view(**ATTRIBUTE_GROUP_SCHEMA) class AttributeGroupViewSet(EvibesViewSet): + """ + Represents a viewset for managing AttributeGroup objects. + + Handles operations related to AttributeGroup, including filtering, + serialization, and retrieval of data. This class is part of the + application's API layer and provides a standardized way to process + requests and responses for AttributeGroup data. + + Attributes: + queryset (QuerySet): QuerySet for retrieving all AttributeGroup objects. + filter_backends (list): List of filter backends used to process filters + in requests. + filterset_fields (list): List of fields on which filtering operations + can be performed. + serializer_class (Serializer): Default serializer class used for + processing AttributeGroup data during non-list view operations. + action_serializer_classes (dict): Mapping of view actions to their + specific serializer classes, allowing customization of serialization + behavior for certain actions. + """ + queryset = AttributeGroup.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["is_active"] @@ -133,6 +188,27 @@ class AttributeGroupViewSet(EvibesViewSet): @extend_schema_view(**ATTRIBUTE_SCHEMA) class AttributeViewSet(EvibesViewSet): + """ + Handles operations related to Attribute objects within the application. + + Provides a set of API endpoints to interact with Attribute data. This class + manages querying, filtering, and serialization of Attribute objects, allowing + dynamic control over the data returned, such as filtering by specific fields + or retrieving detailed versus simplified information depending on the request. + + Attributes: + queryset: The base QuerySet used to represent the set of Attribute + objects available to this viewset. + filter_backends: Defines the backends used for filtering request data, + enabling query flexibility. + filterset_fields: A list of model fields that can be filtered via the API. + serializer_class: Represents the serializer used by default for + serialization and deserialization of Attribute data. + action_serializer_classes: A mapping that defines serializers used for + specific actions, such as returning less detailed data for a `list` + action. + """ + queryset = Attribute.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["group", "value_type", "is_active"] @@ -144,6 +220,23 @@ class AttributeViewSet(EvibesViewSet): @extend_schema_view(**ATTRIBUTE_VALUE_SCHEMA) class AttributeValueViewSet(EvibesViewSet): + """ + A viewset for managing AttributeValue objects. + + This viewset provides functionality for listing, retrieving, creating, updating, and deleting + AttributeValue objects. It integrates with Django REST Framework's viewset mechanisms and uses + appropriate serializers for different actions. Filtering capabilities are provided through the + DjangoFilterBackend. + + Attributes: + queryset (QuerySet): The base queryset for AttributeValue objects. + filter_backends (list): A list of filtering backends applied to the viewset. + filterset_fields (list): Fields of the model that can be used for filtering. + serializer_class (Serializer): The default serializer class for the viewset. + action_serializer_classes (dict): A dictionary mapping action names to their corresponding + serializer classes. + """ + queryset = AttributeValue.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["attribute", "is_active"] @@ -155,6 +248,34 @@ class AttributeValueViewSet(EvibesViewSet): @extend_schema_view(**CATEGORY_SCHEMA) class CategoryViewSet(EvibesViewSet): + """ + Manages views for Category-related operations. + + The CategoryViewSet class is responsible for handling operations related to + the Category model in the system. It supports retrieving, filtering, and + serializing category data. The viewset also enforces permissions to ensure + that only authorized users can access specific data. + + Attributes: + queryset: The base queryset used to retrieve category data, including + prefetching related objects such as parents, children, attributes, + and tags. + filter_backends: A list of backends for applying filters to the category + data. + filterset_class: The filter class used to define filtering behavior for + the category queryset. + serializer_class: The default serializer class used for category objects + when no specific action serializer is applied. + action_serializer_classes: A dictionary mapping specific viewset actions + (e.g., "list") to their corresponding serializer classes. + + Methods: + get_queryset(): + Retrieves the queryset for the viewset, applying permission checks + and filtering out inactive categories for users without sufficient + permissions. + """ + queryset = Category.objects.all().prefetch_related("parent", "children", "attributes", "tags") filter_backends = [DjangoFilterBackend] filterset_class = CategoryFilter @@ -162,6 +283,31 @@ class CategoryViewSet(EvibesViewSet): action_serializer_classes = { "list": CategorySimpleSerializer, } + lookup_field = "lookup_value" + lookup_url_kwarg = "lookup_value" + additional = {"seo_meta": "ALLOW"} + + def get_object(self): + queryset = self.filter_queryset(self.get_queryset()) + lookup_value = self.kwargs[self.lookup_url_kwarg] + + obj = None + + try: + uuid_obj = UUID(lookup_value) + obj = queryset.filter(uuid=uuid_obj).first() + except (ValueError, TypeError): + pass + + if not obj: + obj = queryset.filter(slug=lookup_value).first() + + if not obj: + name = "Category" + raise Http404(f"{name} does not exist: {lookup_value}") + + self.check_object_permissions(self.request, obj) + return obj def get_queryset(self): qs = super().get_queryset() @@ -169,8 +315,89 @@ class CategoryViewSet(EvibesViewSet): return qs return qs.filter(is_active=True) + @action( + detail=True, + methods=["get"], + url_path="meta", + permission_classes=[ + AllowAny, + ], + ) + def seo_meta(self, request, **kwargs): + category = self.get_object() + + title = f"{category.name} | {config.PROJECT_NAME}" + description = (category.description or "")[:180] + canonical = f"https://{config.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/catalog/{category.slug}" + og_image = request.build_absolute_uri(category.image.url) if getattr(category, "image", None) else "" + + og = { + "title": title, + "description": description, + "type": "website", + "url": canonical, + "image": og_image, + } + tw = {"card": "summary_large_image", "title": title, "description": description} + + crumbs = [("Home", f"https://{config.BASE_DOMAIN}/")] + if category.get_ancestors().exists(): + for c in category.get_ancestors(): + crumbs.append((c.name, f"https://{config.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/catalog/{c.slug}")) + crumbs.append((category.name, canonical)) + + json_ld = [org_schema(), website_schema(), breadcrumb_schema(crumbs), category_schema(category, canonical)] + + product_urls = [] + qs = ( + Product.objects.filter( + is_active=True, + category=category, + brand__is_active=True, + stocks__vendor__is_active=True, + ) + .only("slug") + .distinct()[:24] + ) + for p in qs: + product_urls.append(f"https://{config.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/product/{p.slug}") + if product_urls: + json_ld.append(item_list_schema(product_urls)) + + payload = { + "title": title, + "description": description, + "canonical": canonical, + "robots": "index,follow", + "open_graph": og, + "twitter": tw, + "json_ld": json_ld, + } + return Response(SeoSnapshotSerializer(payload).data) + class BrandViewSet(EvibesViewSet): + """ + Represents a viewset for managing Brand instances. + + This class provides functionality for querying, filtering, and + serializing Brand objects. It uses Django's ViewSet framework + to simplify the implementation of API endpoints for Brand objects. + + Attributes: + queryset: The base queryset containing all Brand instances. + filter_backends: A list of filtering backends to apply to the + queryset. The default is [DjangoFilterBackend]. + filterset_class: The filter class used to define the filtering + logic for this viewset. The default is BrandFilter. + serializer_class: The default serializer class used for the + detailed representation of Brand objects. The default is + BrandDetailSerializer. + action_serializer_classes: A dictionary mapping specific actions + to their corresponding serializer classes. The "list" action + uses the BrandSimpleSerializer class. + """ + queryset = Brand.objects.all() filter_backends = [DjangoFilterBackend] filterset_class = BrandFilter @@ -178,10 +405,126 @@ class BrandViewSet(EvibesViewSet): action_serializer_classes = { "list": BrandSimpleSerializer, } + lookup_field = "lookup_value" + lookup_url_kwarg = "lookup_value" + additional = {"seo_meta": "ALLOW"} + + def get_object(self): + queryset = self.filter_queryset(self.get_queryset()) + lookup_value = self.kwargs[self.lookup_url_kwarg] + + obj = None + + try: + uuid_obj = UUID(lookup_value) + obj = queryset.filter(uuid=uuid_obj).first() + except (ValueError, TypeError): + pass + + if not obj: + obj = queryset.filter(slug=lookup_value).first() + + if not obj: + name = "Brand" + raise Http404(f"{name} does not exist: {lookup_value}") + + self.check_object_permissions(self.request, obj) + return obj + + def get_queryset(self): + queryset = Brand.objects.all() + + if self.request.user.has_perm("view_category"): + queryset = queryset.prefetch_related("categories") + else: + queryset = queryset.prefetch_related( + Prefetch("categories", queryset=Category.objects.filter(is_active=True)) + ) + + return queryset + + @action( + detail=True, + methods=["get"], + url_path="meta", + permission_classes=[ + AllowAny, + ], + ) + def seo_meta(self, request, **kwargs): + brand = self.get_object() + + title = f"{brand.name} | {config.PROJECT_NAME}" + description = (brand.description or "")[:180] + canonical = f"https://{config.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/brand/{brand.slug}" + + logo_url = ( + request.build_absolute_uri(brand.big_logo.url) + if getattr(brand, "big_logo", None) + else request.build_absolute_uri(brand.small_logo.url) + if getattr(brand, "small_logo", None) + else "" + ) + + og = { + "title": title, + "description": description, + "type": "website", + "url": canonical, + "image": logo_url, + } + tw = {"card": "summary_large_image", "title": title, "description": description} + + crumbs = [ + ("Home", f"https://{config.BASE_DOMAIN}/"), + (brand.name, canonical), + ] + + json_ld = [ + org_schema(), + website_schema(), + breadcrumb_schema(crumbs), + brand_schema(brand, canonical, logo_url=logo_url), + ] + + payload = { + "title": title, + "description": description, + "canonical": canonical, + "robots": "index,follow", + "open_graph": og, + "twitter": tw, + "json_ld": json_ld, + } + return Response(SeoSnapshotSerializer(payload).data) @extend_schema_view(**PRODUCT_SCHEMA) class ProductViewSet(EvibesViewSet): + """ + Manages operations related to the `Product` model in the system. + + This class provides a viewset for managing products, including their filtering, serialization, + and operations on specific instances. It extends from `EvibesViewSet` to use common + functionality and integrates with the Django REST framework for RESTful API operations. + Includes methods for retrieving product details, applying permissions, and accessing + related feedback of a product. + + Attributes: + queryset: The base queryset to retrieve `Product` objects with prefetch optimization. + filter_backends: Specifies the filtering mechanism for the list views. + filterset_class: Defines the filter class to be used for filtering products. + serializer_class: The default serializer class for product details. + action_serializer_classes: Specific serializer mappings for action methods. + lookup_field: Field representing the object's lookup value in URLs. + lookup_url_kwarg: Field key used to extract the object's lookup value from URL. + + Methods: + get_queryset: Retrieves the queryset with user-specific filtering applied. + get_object: Fetches a single object based on its identifier, applying permissions. + feedbacks: Fetches feedback associated with a specific product. + """ + queryset = Product.objects.prefetch_related("tags", "attributes", "stocks", "images").all() filter_backends = [DjangoFilterBackend] filterset_class = ProductFilter @@ -191,12 +534,18 @@ class ProductViewSet(EvibesViewSet): } lookup_field = "lookup_value" lookup_url_kwarg = "lookup_value" + additional = {"seo_meta": "ALLOW"} def get_queryset(self): qs = super().get_queryset() if self.request.user.has_perm("core.view_product"): return qs - return qs.filter(is_active=True) + return qs.filter( + is_active=True, + brand__is_active=True, + category__is_active=True, + stocks__vendor__is_active=True, + ) def get_object(self): queryset = self.filter_queryset(self.get_queryset()) @@ -225,18 +574,85 @@ class ProductViewSet(EvibesViewSet): lookup_val = kwargs.get(self.lookup_field) try: product = Product.objects.get(uuid=lookup_val) - feedbacks: QuerySet[Feedback] = ( # type: ignore + feedbacks = ( Feedback.objects.filter(order_product__product=product) if request.user.has_perm("core.view_feedback") else Feedback.objects.filter(order_product__product=product, is_active=True) ) + # noinspection PyTypeChecker return Response(data=FeedbackDetailSerializer(feedbacks, many=True).data) except Product.DoesNotExist: name = "Product" return Response(status=status.HTTP_404_NOT_FOUND, data={"detail": _(f"{name} does not exist: {uuid}")}) + @action( + detail=True, + methods=["get"], + url_path="meta", + permission_classes=[ + AllowAny, + ], + ) + def seo_meta(self, request, **kwargs): + p = self.get_object() + images = list(p.images.all()[:6]) + rating = {"value": p.rating, "count": p.feedbacks_count} + title = f"{p.name} | {config.PROJECT_NAME}" + description = (p.description or "")[:180] + canonical = f"https://{config.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/product/{p.slug}" + og = { + "title": title, + "description": description, + "type": "product", + "url": canonical, + "image": request.build_absolute_uri(images[0].image.url) if images else "", + } + tw = {"card": "summary_large_image", "title": title, "description": description} + + crumbs = [("Home", f"https://{config.BASE_DOMAIN}/")] + if p.category: + for c in p.category.get_ancestors(include_self=True): + crumbs.append((c.name, f"https://{config.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/catalog/{c.slug}")) + crumbs.append((p.name, canonical)) + + json_ld = [org_schema(), website_schema()] + if crumbs: + json_ld.append(breadcrumb_schema(crumbs)) + json_ld.append(product_schema(p, images, rating=rating)) + + payload = { + "title": title, + "description": description, + "canonical": canonical, + "robots": "index,follow", + "open_graph": og, + "twitter": tw, + "json_ld": json_ld, + } + return Response(SeoSnapshotSerializer(payload).data) + class VendorViewSet(EvibesViewSet): + """ + Represents a viewset for managing Vendor objects. + + This viewset allows fetching, filtering, and serializing Vendor data. + It defines the queryset, filter configurations, and serializer classes + used to handle different actions. The purpose of this class is to + provide streamlined access to Vendor-related resources through the + Django REST framework. + + Attributes: + queryset: A QuerySet containing all Vendor objects. + filter_backends: A list containing configured filter backends. + filterset_fields: A list of fields that can be used for filtering + Vendor records. + serializer_class: The default serializer class used for this + viewset. + action_serializer_classes: A dictionary mapping specific actions + (e.g., "list") to custom serializer classes for those actions. + """ + queryset = Vendor.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["name", "markup_percent", "is_active"] @@ -248,6 +664,27 @@ class VendorViewSet(EvibesViewSet): @extend_schema_view(**FEEDBACK_SCHEMA) class FeedbackViewSet(EvibesViewSet): + """ + Representation of a view set handling Feedback objects. + + This class manages operations related to Feedback objects, including listing, + filtering, and retrieving details. The purpose of this view set is to provide + different serializers for different actions and implement permission-based + handling of accessible Feedback objects. It extends the base `EvibesViewSet` + and makes use of Django's filtering system for querying data. + + Attributes: + queryset: The base queryset for Feedback objects used in this view set. + filter_backends: List of filter backends to apply, specifically + `DjangoFilterBackend` for this view set. + filterset_class: Class specifying the filter set used for querying + Feedback objects. + serializer_class: Default serializer class used for this view set. + action_serializer_classes: A dictionary mapping action names to specific + serializer classes. For example, the "list" action uses + `FeedbackSimpleSerializer`. + """ + queryset = Feedback.objects.all() filter_backends = [DjangoFilterBackend] filterset_class = FeedbackFilter @@ -265,6 +702,52 @@ class FeedbackViewSet(EvibesViewSet): @extend_schema_view(**ORDER_SCHEMA) class OrderViewSet(EvibesViewSet): + """ + ViewSet for managing orders and related operations. + + This class provides functionality to retrieve, modify, and manage order objects. + It includes various endpoints for handling order operations such as adding or + removing products, performing purchases for registered as well as unregistered + users, and retrieving the current authenticated user's pending orders. + + The ViewSet uses multiple serializers based on the specific action being + performed and enforces permissions accordingly while interacting with order data. + + Attributes: + lookup_field (str): Field name used for performing object lookup. + lookup_url_kwarg (str): URL keyword argument used for object lookup. Defaults + to `lookup_field`. + queryset (QuerySet): Default queryset for retrieving order objects, with + prefetched related order products. + filter_backends (list): List of backends applied for filtering the queryset. + filterset_class (type): Filtering class applied to the queryset for request-based + customizations. + serializer_class (type): Default serializer used if no specific serializer is + defined for an action. + action_serializer_classes (dict): Mapping of actions to their respective serializers. + Used to determine the serializer dynamically based on the requested action. + additional (dict): Additional settings for specific actions. + + Methods: + get_serializer_class: Returns the serializer class based on the specific + action being requested. + get_queryset: Adjusts the queryset based on the request user's permissions, + favoring anonymous or limited query access for unauthenticated users. + get_object: Retrieves a specific order object based on the lookup value, either + its UUID or a human-readable ID. + current: Retrieves the authenticated user's current pending order. + buy: Processes an order purchase for an authenticated user with optional parameters + such as balance and payment overrides, promocodes, and billing/shipping addresses. + buy_unregistered: Processes an order purchase for unauthenticated users with product, + customer details, and payment information. + add_order_product: Adds a product, with optional attributes, to an order specified by UUID. + remove_order_product: Removes a product, with optional attributes, from an order specified + by UUID. + bulk_add_order_products: Adds multiple products with optional attributes to an order. + bulk_remove_order_products: Removes multiple products with optional attributes from + an order. + """ + lookup_field = "lookup_value" lookup_url_kwarg = "lookup_value" queryset = Order.objects.prefetch_related("order_products").all() @@ -331,6 +814,7 @@ class OrderViewSet(EvibesViewSet): promocode_uuid=serializer.validated_data.get("promocode_uuid"), shipping_address=serializer.validated_data.get("shipping_address_uuid"), billing_address=serializer.validated_data.get("billing_address_uuid"), + chosen_products=serializer.validated_data.get("chosen_products"), ) match str(type(instance)): case "": @@ -404,7 +888,7 @@ class OrderViewSet(EvibesViewSet): serializer.is_valid(raise_exception=True) lookup_val = kwargs.get(self.lookup_field) try: - order = Order.objects.get(uuid=lookup_val) + order = Order.objects.get(uuid=str(lookup_val)) if not (request.user.has_perm("core.add_orderproduct") or request.user == order.user): raise PermissionDenied(permission_denied_message) @@ -435,6 +919,34 @@ class OrderViewSet(EvibesViewSet): @extend_schema_view(**ORDER_PRODUCT_SCHEMA) class OrderProductViewSet(EvibesViewSet): + """ + Provides a viewset for managing OrderProduct entities. + + This viewset enables CRUD operations and custom actions specific to the + OrderProduct model. It includes filtering, permission checks, and + serializer switching based on the requested action. Additionally, it + provides a detailed action for handling feedback on OrderProduct + instances. + + Attributes: + queryset (QuerySet): The base queryset for OrderProduct objects. + filter_backends (list): Backends responsible for handling filtering + mechanisms. + filterset_fields (list[str]): Fields available for API filtering. + serializer_class (Serializer): Default serializer class for CRUD + operations. + action_serializer_classes (dict[str, Serializer]): Mapping of + specific actions to their corresponding serializer classes. + + Methods: + get_queryset: Overrides the default queryset to enforce user + permissions. + + Actions: + do_feedback: Custom action to add, remove, or manage feedback for + an OrderProduct instance. + """ + queryset = OrderProduct.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["order", "product", "status", "is_active"] @@ -478,6 +990,28 @@ class OrderProductViewSet(EvibesViewSet): class ProductImageViewSet(EvibesViewSet): + """ + Manages operations related to Product images in the application. + + This class-based view set provides endpoints to manage and access ProductImage + objects. It supports filtering, serialization, and customized serializers for + different actions to handle ProductImage data. + + Attributes: + queryset (QuerySet): A Django QuerySet consisting of all ProductImage + instances within the system. + filter_backends (list): A list of filter backends that determine the + filtering behavior on querysets. Set to [DjangoFilterBackend]. + filterset_fields (list): Fields that can be used for filtering data. + Includes "product", "priority", and "is_active". + serializer_class (Serializer): The default serializer class used for + serializing and deserializing ProductImage data. Set to + ProductImageDetailSerializer. + action_serializer_classes (dict): A mapping of action names to specific + serializer classes. For the "list" action, ProductImageSimpleSerializer + is used. + """ + queryset = ProductImage.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["product", "priority", "is_active"] @@ -488,6 +1022,26 @@ class ProductImageViewSet(EvibesViewSet): class PromoCodeViewSet(EvibesViewSet): + """ + Manages the retrieval and handling of PromoCode instances through various + API actions. + + This class extends the functionality of the EvibesViewSet to provide a + customized view set for PromoCode objects. It includes filtering capabilities, + uses specific serializers for different actions, and limits data access + based on user permissions. The primary purpose is to enable API operations + related to PromoCodes while enforcing security and filtering. + + Attributes: + queryset: A queryset of all PromoCode objects in the database. + filter_backends: Backend classes responsible for filtering queryset data. + filterset_fields: Fields supported for filtering PromoCode data. + serializer_class: The default serializer class used for instances when no + specific action-based serializer is defined. + action_serializer_classes: A dictionary mapping specific actions (like + "list") to their corresponding serializer classes. + """ + queryset = PromoCode.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["code", "discount_amount", "discount_percent", "start_time", "end_time", "used_on", "is_active"] @@ -507,6 +1061,15 @@ class PromoCodeViewSet(EvibesViewSet): class PromotionViewSet(EvibesViewSet): + """ + Represents a view set for managing promotions. + + This class provides operations to handle retrieval, filtering, and serialization + of promotion objects. It leverages Django REST framework capabilities such as + queryset management, filter backends, and serializer customization for handling + different views or actions efficiently. + """ + queryset = Promotion.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["name", "discount_percent", "is_active"] @@ -517,6 +1080,27 @@ class PromotionViewSet(EvibesViewSet): class StockViewSet(EvibesViewSet): + """ + Handles operations related to Stock data in the system. + + The StockViewSet class is a viewset that provides methods for retrieving, + filtering, and serializing Stock data. It uses Django's filter + backends to enable filtering based on specified fields and supports + custom serializers for different actions. + + Attributes: + queryset (QuerySet): A queryset of all Stock objects. + filter_backends (list): A list of filter backends to be applied. + filterset_fields (list of str): Fields on which the filtering + is permitted. These fields include "vendor", "product", "sku", + and "is_active". + serializer_class (Serializer): The primary serializer used + for Stock detail representation. + action_serializer_classes (dict): A dictionary mapping action names + to their respective serializers. For the "list" action, + StockSimpleSerializer is used. + """ + queryset = Stock.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["vendor", "product", "sku", "is_active"] @@ -528,6 +1112,45 @@ class StockViewSet(EvibesViewSet): @extend_schema_view(**WISHLIST_SCHEMA) class WishlistViewSet(EvibesViewSet): + """ + ViewSet for managing Wishlist operations. + + The WishlistViewSet provides endpoints for interacting with a user's wish list, + allowing for the retrieval, modification, and customization of products within + the wish list. This ViewSet facilitates functionality such as adding, removing, + and bulk actions for wishlist products. Permission checks are integrated to + ensure that users can only manage their own wishlists unless explicit permissions + are granted. + + Attributes + ---------- + queryset : QuerySet + The base queryset for retrieving wishlist objects. + filter_backends : list + List of backend filters to apply to the queryset. + filterset_fields : list + Fields for which filtering is allowed in queries. + serializer_class : Serializer + The default serializer class used for wishlist objects. + action_serializer_classes : dict + A map of serializers used for specific actions. + + Methods + ------- + get_queryset() + Retrieves the queryset, filtered based on the user's permissions. + current(request) + Retrieves the currently authenticated user's wishlist. + add_wishlist_product(request, **kwargs) + Adds a product to a specific wishlist. + remove_wishlist_product(request, **kwargs) + Removes a product from a specific wishlist. + bulk_add_wishlist_products(request, **kwargs) + Adds multiple products to a specific wishlist. + bulk_remove_wishlist_products(request, **kwargs) + Removes multiple products from a specific wishlist. + """ + queryset = Wishlist.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["user", "is_active"] @@ -628,6 +1251,22 @@ class WishlistViewSet(EvibesViewSet): @extend_schema_view(**ADDRESS_SCHEMA) class AddressViewSet(EvibesViewSet): + """ + This class provides viewset functionality for managing `Address` objects. + + The AddressViewSet class enables CRUD operations, filtering, and custom actions + related to address entities. It includes specialized behaviors for different HTTP + methods, serializer overrides, and permission handling based on the request context. + + Attributes: + pagination_class: Specifies pagination class for the viewset, set to None. + filter_backends: List of backend classes for filtering querysets. + filterset_class: Specifies the filter class for filtering address objects. + queryset: Default queryset containing all Address objects. + serializer_class: Default serializer class for address objects. + additional: Dictionary of additional options for this viewset. + """ + pagination_class = None filter_backends = [DjangoFilterBackend] filterset_class = AddressFilter @@ -687,6 +1326,27 @@ class AddressViewSet(EvibesViewSet): class ProductTagViewSet(EvibesViewSet): + """ + Handles operations related to Product Tags within the application. + + This class provides functionality for retrieving, filtering, and serializing + Product Tag objects. It supports flexible filtering on specific attributes + using the specified filter backend and dynamically uses different serializers + based on the action being performed. + + Attributes: + queryset: The base queryset containing all ProductTag objects. + filter_backends: A list of backends used to filter the queryset. + filterset_fields: Fields available for filtering the queryset. Includes + 'tag_name' for filtering by the name of the tag, and 'is_active' for + filtering active/inactive tags. + serializer_class: The default serializer class is used when no specific + serializer is defined for an action. + action_serializer_classes: A dictionary mapping specific actions (e.g., + 'list') to custom serializers. Uses ProductTagSimpleSerializer + for the 'list' action. + """ + queryset = ProductTag.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["tag_name", "is_active"] diff --git a/docker-compose.yml b/docker-compose.yml index f880c9ab..7e5b89d0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -136,7 +136,38 @@ services: - .env environment: - BROKER_URL=${CELERY_BROKER_URL} + - TZ=${TIME_ZONE} depends_on: + database: + condition: service_healthy + redis: + condition: service_healthy + elasticsearch: + condition: service_healthy + logging: *default-logging + healthcheck: + test: [ "CMD-SHELL", "celery -A evibes status | grep -q 'OK'" ] + interval: 30s + timeout: 10s + retries: 5 + start_period: 15s + + stock_updater: + container_name: stock_updater + build: + context: . + dockerfile: ./Dockerfiles/Dockerfile.stock_updater + restart: always + volumes: + - .:/app + env_file: + - .env + environment: + - BROKER_URL=${CELERY_BROKER_URL} + - TZ=${TIME_ZONE} + depends_on: + database: + condition: service_healthy redis: condition: service_healthy elasticsearch: @@ -159,8 +190,11 @@ services: - .:/app env_file: - .env + environment: + - BROKER_URL=${CELERY_BROKER_URL} + - TZ=${TIME_ZONE} depends_on: - worker: + database: condition: service_healthy logging: *default-logging healthcheck: diff --git a/evibes/api_urls.py b/evibes/api_urls.py index 683bbae6..016efca4 100644 --- a/evibes/api_urls.py +++ b/evibes/api_urls.py @@ -17,12 +17,9 @@ from core.views import ( from evibes.settings import SPECTACULAR_PLATFORM_SETTINGS urlpatterns = [ - path(r"health/", include("health_check.urls")), + path(r"health/", include("health_check.urls", namespace="health_check")), path("prometheus/", include("django_prometheus.urls")), - path( - r"graphql/", - csrf_exempt(CustomGraphQLView.as_view(graphiql=True, schema=schema)), - ), + path(r"graphql/", csrf_exempt(CustomGraphQLView.as_view(graphiql=True, schema=schema)), name="graphql-platform"), path( r"docs/", SpectacularAPIView.as_view(urlconf="evibes.api_urls", custom_settings=SPECTACULAR_PLATFORM_SETTINGS), @@ -42,10 +39,11 @@ urlpatterns = [ path(r"i18n/", include("django.conf.urls.i18n")), path(r"favicon.ico", favicon_view), path(r"", index), - path(r"", include("core.api_urls")), - path(r"auth/", include("vibes_auth.urls")), - path(r"payments/", include("payments.urls")), - path(r"blog/", include("blog.urls")), + path(r"", include("core.api_urls", namespace="core")), + path(r"auth/", include("vibes_auth.urls", namespace="vibes_auth")), + path(r"payments/", include("payments.urls", namespace="payments")), + path(r"blog/", include("blog.urls", namespace="blog")), + path("admin/doc/", include("django.contrib.admindocs.urls")), ] + i18n_patterns(path("admin/", admin.site.urls)) if settings.DEBUG: diff --git a/evibes/b2b_urls.py b/evibes/b2b_urls.py index 8bd89af0..aeeeee23 100644 --- a/evibes/b2b_urls.py +++ b/evibes/b2b_urls.py @@ -7,8 +7,6 @@ from core.views import CustomRedocView, CustomSwaggerView, favicon_view from evibes.settings import SPECTACULAR_B2B_SETTINGS urlpatterns = [ - # path(r'graphql/', csrf_exempt(CustomGraphQLView.as_view(graphiql=True, schema=schema))), - path("prometheus/", include("django_prometheus.urls")), path( r"docs/", SpectacularAPIView.as_view(urlconf="evibes.b2b_urls", custom_settings=SPECTACULAR_B2B_SETTINGS), @@ -17,7 +15,7 @@ urlpatterns = [ path(r"docs/swagger/", CustomSwaggerView.as_view(url_name="schema-b2b"), name="swagger-ui-b2b"), path(r"docs/redoc/", CustomRedocView.as_view(url_name="schema-b2b"), name="redoc-ui-b2b"), path(r"favicon.ico", favicon_view), - path(r"", include("core.b2b_urls")), + path(r"", include("core.b2b_urls", namespace="core_b2b")), ] if settings.DEBUG: diff --git a/evibes/celery.py b/evibes/celery.py index d0479561..5ddabb48 100644 --- a/evibes/celery.py +++ b/evibes/celery.py @@ -2,37 +2,27 @@ import os from celery import Celery -from evibes.settings import REDIS_PASSWORD, TIME_ZONE - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "evibes.settings") app = Celery("evibes") app.conf.update( - broker_url=f"redis://:{REDIS_PASSWORD}@redis:6379/0", - result_backend=f"redis://:{REDIS_PASSWORD}@redis:6379/0", worker_hijack_root_logger=False, worker_log_format="[%(asctime)s: %(levelname)s/%(processName)s] %(name)s: %(message)s", worker_task_log_format="[%(asctime)s: %(levelname)s/%(processName)s] %(name)s: %(message)s", - worker_autoscale=(10, 3), broker_connection_retry_on_startup=True, - timezone=TIME_ZONE, task_serializer="json", result_serializer="json", result_compression="zlib", accept_content=["json"], - broker_transport_options={ - "retry_policy": {"interval_start": 0.1, "interval_step": 0.2, "max_retries": 5}, - "visibility_timeout": 3600, - }, task_acks_late=True, task_reject_on_worker_lost=True, - worker_prefetch_multiplier=1, - worker_max_tasks_per_child=100, - task_soft_time_limit=10800, - task_time_limit=21600, ) +app.conf.task_routes = { + "core.tasks.update_products_task": {"queue": "stock_updater"}, +} + app.config_from_object("django.conf:settings", namespace="CELERY") app.autodiscover_tasks() diff --git a/evibes/ftpstorage.py b/evibes/ftpstorage.py new file mode 100644 index 00000000..7e87e0f6 --- /dev/null +++ b/evibes/ftpstorage.py @@ -0,0 +1,13 @@ +from urllib.parse import urlparse + +from storages.backends.ftp import FTPStorage + + +class AbsoluteFTPStorage(FTPStorage): # type: ignore + # noinspection PyProtectedMember + + def _get_config(self): + cfg = super()._get_config() + url = urlparse(self.location) + cfg["path"] = url.path or cfg["path"] + return cfg diff --git a/evibes/locale/ar_AR/LC_MESSAGES/django.mo b/evibes/locale/ar_AR/LC_MESSAGES/django.mo index 0fc354f2..401478ad 100644 Binary files a/evibes/locale/ar_AR/LC_MESSAGES/django.mo and b/evibes/locale/ar_AR/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/ar_AR/LC_MESSAGES/django.po b/evibes/locale/ar_AR/LC_MESSAGES/django.po index 9a7d8f60..14eecf75 100644 --- a/evibes/locale/ar_AR/LC_MESSAGES/django.po +++ b/evibes/locale/ar_AR/LC_MESSAGES/django.po @@ -1,201 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: ar-ar\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "اسم المشروع" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "اسم نطاق الواجهة الأمامية" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "اسم النطاق الأساسي" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "اسم الشركة" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "عنوان الشركة" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "رقم هاتف الشركة" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "مضيف SMTP" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "منفذ SMTP" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "استخدام TLS" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "استخدام SSL" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "اسم مستخدم SMTP" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "كلمة مرور SMTP" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "عنوان مرسل البريد الإلكتروني" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "عنوان URL لبوابة الدفع" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "الرمز المميز لبوابة الدفع" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "الحد الأدنى لمبلغ بوابة الدفع" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "الحد الأقصى لمبلغ بوابة الدفع" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "مفتاح API لسعر الصرف" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "عنوان URL لواجهة برمجة تطبيقات OpenStreetMap Nominatim" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "مفتاح واجهة برمجة تطبيقات OpenAI" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "مفتاح واجهة برمجة التطبيقات المجردة" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "وكيل HTTP" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "تعطيل وظيفة الشراء" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "كيان لتخزين بيانات الإعلانات" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "كيان لتخزين بيانات التحليلات" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "الخيارات العامة" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "خيارات البريد الإلكتروني" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "خيارات بوابة الدفع" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "خيارات الميزات" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "خيارات تحسين محركات البحث" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "الصفحة الرئيسية" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "واجهة المتجر" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "مستندات GraphQL" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "مستندات النظام الأساسي REST" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "مستندات B2B REST" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "الدعم" diff --git a/evibes/locale/cs_CZ/LC_MESSAGES/django.mo b/evibes/locale/cs_CZ/LC_MESSAGES/django.mo index 0fc354f2..e6d117e7 100644 Binary files a/evibes/locale/cs_CZ/LC_MESSAGES/django.mo and b/evibes/locale/cs_CZ/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/cs_CZ/LC_MESSAGES/django.po b/evibes/locale/cs_CZ/LC_MESSAGES/django.po index 9a7d8f60..068ab567 100644 --- a/evibes/locale/cs_CZ/LC_MESSAGES/django.po +++ b/evibes/locale/cs_CZ/LC_MESSAGES/django.po @@ -1,201 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: cs-cz\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "Název projektu" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "Název domény frontendu" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "Název základní domény" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "Název společnosti" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "Adresa společnosti" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "Telefonní číslo společnosti" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "SMTP host" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "Port SMTP" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "Použití protokolu TLS" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "Použití protokolu SSL" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "Uživatelské jméno SMTP" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "Heslo SMTP" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "Adresa odesílatele e-mailů" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "Adresa URL platební brány" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "Token platební brány" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "Minimální částka platební brány" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "Maximální částka platební brány" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "Klíč API pro směnný kurz" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "URL rozhraní API OpenStreetMap Nominatim" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "Klíč API OpenAI" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "Abstraktní klíč API" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "Proxy server HTTP" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "Zakázat funkci nákupu" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "Subjekt pro ukládání dat inzerátů" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "Subjekt pro ukládání analytických dat" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "Obecné možnosti" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "Možnosti e-mailu" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "Možnosti platební brány" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "Možnosti funkcí" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "Možnosti SEO" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "Home" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "Výloha" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "Dokumenty GraphQL" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "Dokumenty platformy REST" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "Dokumenty B2B REST" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "Podpora" diff --git a/evibes/locale/da_DK/LC_MESSAGES/django.mo b/evibes/locale/da_DK/LC_MESSAGES/django.mo index 0fc354f2..3c8570fa 100644 Binary files a/evibes/locale/da_DK/LC_MESSAGES/django.mo and b/evibes/locale/da_DK/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/da_DK/LC_MESSAGES/django.po b/evibes/locale/da_DK/LC_MESSAGES/django.po index 9a7d8f60..617b3c79 100644 --- a/evibes/locale/da_DK/LC_MESSAGES/django.po +++ b/evibes/locale/da_DK/LC_MESSAGES/django.po @@ -1,201 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: da-dk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "Projektets navn" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "Frontend-domænenavn" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "Basisdomænenavn" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "Virksomhedens navn" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "Virksomhedens adresse" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "Virksomhedens telefonnummer" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "SMTP-vært" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "SMTP-port" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "Brug TLS" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "Brug SSL" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "SMTP-brugernavn" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "SMTP-adgangskode" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "Adressen på e-mailens afsender" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "URL til betalingsgateway" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "Token til betalingsgateway" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "Minimumsbeløb for betalingsgateway" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "Betalingsgatewayens maksimale beløb" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "API-nøgle til valutakurs" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "OpenStreetMap Nominatim API URL" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "OpenAI API-nøgle" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "Abstrakt API-nøgle" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "HTTP-proxy" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "Deaktiver købsfunktionalitet" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "En enhed til lagring af annonceringsdata" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "En enhed til lagring af analysedata" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "Generelle indstillinger" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "Indstillinger for e-mail" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "Muligheder for betalingsgateway" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "Funktioner Indstillinger" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "SEO-muligheder" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "Hjem" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "Butiksfacade" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "GraphQL-dokumenter" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "Platform REST-dokumenter" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "B2B REST-dokumenter" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "Støtte" diff --git a/evibes/locale/de_DE/LC_MESSAGES/django.mo b/evibes/locale/de_DE/LC_MESSAGES/django.mo index 0fc354f2..b53a8e0f 100644 Binary files a/evibes/locale/de_DE/LC_MESSAGES/django.mo and b/evibes/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/de_DE/LC_MESSAGES/django.po b/evibes/locale/de_DE/LC_MESSAGES/django.po index 9a7d8f60..fbd0b63c 100644 --- a/evibes/locale/de_DE/LC_MESSAGES/django.po +++ b/evibes/locale/de_DE/LC_MESSAGES/django.po @@ -1,201 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: de-de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "Name des Projekts" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "Frontend-Domain-Name" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "Basis-Domainname" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "Name des Unternehmens" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "Anschrift des Unternehmens" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "Telefonnummer des Unternehmens" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "SMTP-Host" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "SMTP-Port" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "Use TLS" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "Use SSL" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "SMTP-Benutzername" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "SMTP-Kennwort" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "Die Adresse des Absenders der E-Mail" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "URL des Zahlungsgateways" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "Zahlungsgateway-Token" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "Mindestbetrag für das Zahlungsgateway" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "Höchstbetrag des Zahlungsgateways" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "Wechselkurs-API-Schlüssel" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "OpenStreetMap Nominatim API URL" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "OpenAI API Key" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "Abstrakter API-Schlüssel" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "HTTP-Proxy" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "Kauffunktionalität deaktivieren" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "Eine Einheit zur Speicherung von Werbedaten" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "Eine Einheit zur Speicherung von Analysedaten" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "Allgemeine Optionen" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "E-Mail-Optionen" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "Zahlungs-Gateway-Optionen" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "Merkmale Optionen" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "SEO-Optionen" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "Startseite" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "Schaufenster" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "GraphQL Docs" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "Plattform REST Docs" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "B2B REST-Dokumente" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "Unterstützung" diff --git a/evibes/locale/en_GB/LC_MESSAGES/django.mo b/evibes/locale/en_GB/LC_MESSAGES/django.mo index 63f7d7fb..467d627b 100644 Binary files a/evibes/locale/en_GB/LC_MESSAGES/django.mo and b/evibes/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/en_GB/LC_MESSAGES/django.po b/evibes/locale/en_GB/LC_MESSAGES/django.po index 9c62dda9..5b4fbabf 100644 --- a/evibes/locale/en_GB/LC_MESSAGES/django.po +++ b/evibes/locale/en_GB/LC_MESSAGES/django.po @@ -5,9 +5,9 @@ # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -17,186 +17,146 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" - #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "Name of the project" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "Frontend domain name" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "Base domain name" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "Name of the company" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "Address of the company" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "Phone number of the company" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "SMTP host" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "SMTP port" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "Use TLS" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "Use SSL" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "SMTP username" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "SMTP password" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "The address of the emails sender" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "Payment gateway URL" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "Payment gateway token" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "Payment gateway minimum amount" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "Payment gateway maximum amount" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "Exchange rate API key" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "OpenStreetMap Nominatim API URL" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "OpenAI API Key" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "Abstract API Key" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "HTTP Proxy" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "Disable buy functionality" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "An entity for storing advertisiment data" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "An entity for storing analytics data" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "General Options" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "Email Options" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "Payment Gateway Options" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "Features Options" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "SEO Options" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "Home" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "Storefront" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "GraphQL Docs" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "Platform REST Docs" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "B2B REST Docs" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "Support" diff --git a/evibes/locale/en_US/LC_MESSAGES/django.mo b/evibes/locale/en_US/LC_MESSAGES/django.mo index 0fc354f2..04719d61 100644 Binary files a/evibes/locale/en_US/LC_MESSAGES/django.mo and b/evibes/locale/en_US/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/en_US/LC_MESSAGES/django.po b/evibes/locale/en_US/LC_MESSAGES/django.po index 9a7d8f60..4aba66ba 100644 --- a/evibes/locale/en_US/LC_MESSAGES/django.po +++ b/evibes/locale/en_US/LC_MESSAGES/django.po @@ -1,201 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: en-us\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "Name of the project" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "Frontend domain name" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "Base domain name" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "Name of the company" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "Address of the company" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "Phone number of the company" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "SMTP host" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "SMTP port" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "Use TLS" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "Use SSL" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "SMTP username" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "SMTP password" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "The address of the emails sender" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "Payment gateway URL" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "Payment gateway token" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "Payment gateway minimum amount" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "Payment gateway maximum amount" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "Exchange rate API key" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "OpenStreetMap Nominatim API URL" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "OpenAI API Key" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "Abstract API Key" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "HTTP Proxy" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "Disable buy functionality" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "An entity for storing advertisiment data" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "An entity for storing analytics data" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "General Options" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "Email Options" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "Payment Gateway Options" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "Features Options" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "SEO Options" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "Home" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "Storefront" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "GraphQL Docs" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "Platform REST Docs" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "B2B REST Docs" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "Support" diff --git a/evibes/locale/es_ES/LC_MESSAGES/django.mo b/evibes/locale/es_ES/LC_MESSAGES/django.mo index 0fc354f2..7f49ac2b 100644 Binary files a/evibes/locale/es_ES/LC_MESSAGES/django.mo and b/evibes/locale/es_ES/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/es_ES/LC_MESSAGES/django.po b/evibes/locale/es_ES/LC_MESSAGES/django.po index 9a7d8f60..0ceb55a6 100644 --- a/evibes/locale/es_ES/LC_MESSAGES/django.po +++ b/evibes/locale/es_ES/LC_MESSAGES/django.po @@ -1,201 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: es-es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "Nombre del proyecto" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "Nombre de dominio frontend" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "Nombre de dominio base" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "Nombre de la empresa" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "Dirección de la empresa" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "Número de teléfono de la empresa" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "Host SMTP" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "Puerto SMTP" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "Utilizar TLS" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "Utilizar SSL" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "Nombre de usuario SMTP" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "Contraseña SMTP" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "Dirección del remitente del correo electrónico" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "URL de la pasarela de pago" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "Token de pasarela de pago" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "Importe mínimo de la pasarela de pago" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "Importe máximo de la pasarela de pago" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "Clave API de tipo de cambio" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "URL de la API Nominatim de OpenStreetMap" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "Clave API de OpenAI" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "Clave API abstracta" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "Proxy HTTP" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "Desactivar la función de compra" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "Una entidad para almacenar datos publicitarios" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "Una entidad para almacenar datos analíticos" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "Opciones generales" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "Opciones de correo electrónico" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "Opciones de pasarela de pago" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "Características Opciones" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "Opciones SEO" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "Inicio" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "Escaparate" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "Documentos GraphQL" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "Plataforma REST Docs" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "Documentos B2B REST" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "Ayuda" diff --git a/evibes/locale/fr_FR/LC_MESSAGES/django.mo b/evibes/locale/fr_FR/LC_MESSAGES/django.mo index 0fc354f2..0152adfe 100644 Binary files a/evibes/locale/fr_FR/LC_MESSAGES/django.mo and b/evibes/locale/fr_FR/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/fr_FR/LC_MESSAGES/django.po b/evibes/locale/fr_FR/LC_MESSAGES/django.po index 9a7d8f60..29e11c2b 100644 --- a/evibes/locale/fr_FR/LC_MESSAGES/django.po +++ b/evibes/locale/fr_FR/LC_MESSAGES/django.po @@ -1,201 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: fr-fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "Nom du projet" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "Nom de domaine du frontend" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "Nom de domaine de base" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "Nom de l'entreprise" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "Adresse de l'entreprise" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "Numéro de téléphone de l'entreprise" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "Hôte SMTP" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "SMTP port" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "Utiliser TLS" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "Use SSL" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "Nom d'utilisateur SMTP" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "Mot de passe SMTP" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "L'adresse de l'expéditeur du courrier électronique" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "URL de la passerelle de paiement" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "Jeton de passerelle de paiement" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "Montant minimum de la passerelle de paiement" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "Montant maximum de la passerelle de paiement" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "Clé API pour le taux de change" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "URL de l'API OpenStreetMap Nominatim" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "OpenAI API Key" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "Clé API abstraite" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "HTTP Proxy" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "Désactiver la fonctionnalité d'achat" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "Une entité pour stocker des données publicitaires" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "Une entité pour stocker des données analytiques" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "Options générales" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "Options de courrier électronique" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "Options de passerelle de paiement" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "Caractéristiques Options" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "Options de référencement" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "Accueil" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "Vitrine" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "Docs GraphQL" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "Docs REST de la plateforme" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "B2B REST Docs" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "Soutien" diff --git a/evibes/locale/hi_IN/LC_MESSAGES/django.mo b/evibes/locale/hi_IN/LC_MESSAGES/django.mo index 0fc354f2..47c1f925 100644 Binary files a/evibes/locale/hi_IN/LC_MESSAGES/django.mo and b/evibes/locale/hi_IN/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/hi_IN/LC_MESSAGES/django.po b/evibes/locale/hi_IN/LC_MESSAGES/django.po index 9a7d8f60..75d54335 100644 --- a/evibes/locale/hi_IN/LC_MESSAGES/django.po +++ b/evibes/locale/hi_IN/LC_MESSAGES/django.po @@ -5,9 +5,9 @@ # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -16,34 +16,30 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: evibes/settings/constance.py:18 +#: evibes/settings/constance.py:22 msgid "Name of the project" msgstr "" -#: evibes/settings/constance.py:19 +#: evibes/settings/constance.py:23 msgid "Frontend domain name" msgstr "" -#: evibes/settings/constance.py:20 +#: evibes/settings/constance.py:24 msgid "Base domain name" msgstr "" -#: evibes/settings/constance.py:21 +#: evibes/settings/constance.py:25 msgid "Name of the company" msgstr "" -#: evibes/settings/constance.py:22 +#: evibes/settings/constance.py:26 msgid "Address of the company" msgstr "" -#: evibes/settings/constance.py:23 +#: evibes/settings/constance.py:27 msgid "Phone number of the company" msgstr "" -#: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" - #: evibes/settings/constance.py:28 msgid "SMTP host" msgstr "" @@ -53,11 +49,11 @@ msgid "SMTP port" msgstr "" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" +msgid "Use TLS (0=No, 1=Yes)" msgstr "" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" +msgid "Use SSL (0=No, 1=Yes)" msgstr "" #: evibes/settings/constance.py:32 @@ -100,102 +96,66 @@ msgstr "" msgid "OpenAI API Key" msgstr "" -#: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" msgstr "" -#: evibes/settings/constance.py:46 +#: evibes/settings/constance.py:43 msgid "HTTP Proxy" msgstr "" -#: evibes/settings/constance.py:47 +#: evibes/settings/constance.py:44 msgid "Disable buy functionality" msgstr "" -#: evibes/settings/constance.py:50 +#: evibes/settings/constance.py:47 msgid "An entity for storing advertisiment data" msgstr "" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" msgstr "" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" +#: evibes/settings/constance.py:54 +msgid "General Options" msgstr "" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" msgstr "" diff --git a/evibes/locale/it_IT/LC_MESSAGES/django.mo b/evibes/locale/it_IT/LC_MESSAGES/django.mo index 0fc354f2..1b5bccda 100644 Binary files a/evibes/locale/it_IT/LC_MESSAGES/django.mo and b/evibes/locale/it_IT/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/it_IT/LC_MESSAGES/django.po b/evibes/locale/it_IT/LC_MESSAGES/django.po index 9a7d8f60..5a19bfb8 100644 --- a/evibes/locale/it_IT/LC_MESSAGES/django.po +++ b/evibes/locale/it_IT/LC_MESSAGES/django.po @@ -1,201 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: it-it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "Nome del progetto" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "Nome di dominio del frontend" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "Nome di dominio di base" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "Nome della società" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "Indirizzo dell'azienda" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "Numero di telefono dell'azienda" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "Host SMTP" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "Porta SMTP" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "Utilizzare TLS" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "Utilizzare SSL" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "Nome utente SMTP" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "Password SMTP" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "L'indirizzo del mittente dell'e-mail" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "URL del gateway di pagamento" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "Token del gateway di pagamento" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "Importo minimo del gateway di pagamento" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "Importo massimo del gateway di pagamento" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "Chiave API del tasso di cambio" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "URL dell'API OpenStreetMap Nominatim" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "Chiave API OpenAI" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "Chiave API astratta" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "Proxy HTTP" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "Disattivare la funzionalità di acquisto" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "Un'entità per la memorizzazione dei dati pubblicitari" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "Un'entità per la memorizzazione dei dati analitici" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "Opzioni generali" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "Opzioni e-mail" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "Opzioni di gateway di pagamento" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "Caratteristiche Opzioni" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "Opzioni SEO" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "Casa" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "Storefront" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "Documenti GraphQL" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "Documenti della piattaforma REST" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "Documenti REST B2B" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "Supporto" diff --git a/evibes/locale/ja_JP/LC_MESSAGES/django.mo b/evibes/locale/ja_JP/LC_MESSAGES/django.mo index 0fc354f2..992ead43 100644 Binary files a/evibes/locale/ja_JP/LC_MESSAGES/django.mo and b/evibes/locale/ja_JP/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/ja_JP/LC_MESSAGES/django.po b/evibes/locale/ja_JP/LC_MESSAGES/django.po index 9a7d8f60..00db5aac 100644 --- a/evibes/locale/ja_JP/LC_MESSAGES/django.po +++ b/evibes/locale/ja_JP/LC_MESSAGES/django.po @@ -1,201 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: ja-jp\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "プロジェクト名" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "フロントエンド・ドメイン名" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "ベースドメイン名" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "会社名" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "会社住所" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "会社の電話番号" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "SMTPホスト" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "SMTPポート" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "TLSを使用する" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "SSLの使用" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "SMTPユーザー名" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "SMTPパスワード" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "メール送信者のアドレス" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "決済ゲートウェイURL" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "ペイメントゲートウェイ・トークン" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "ペイメントゲートウェイの最低金額" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "支払ゲートウェイ上限額" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "為替レートAPIキー" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "OpenStreetMap Nominatim API URL" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "OpenAI APIキー" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "抽象APIキー" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "HTTPプロキシ" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "購入機能を無効にする" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "広告データを保存するエンティティ" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "分析データを保存するエンティティ" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "一般オプション" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "Eメールオプション" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "ペイメントゲートウェイオプション" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "機能オプション" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "SEOオプション" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "ホーム" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "ストアフロント" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "GraphQLドキュメント" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "プラットフォームRESTドキュメント" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "B2B REST ドキュメント" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "サポート" diff --git a/evibes/locale/kk_KZ/LC_MESSAGES/django.mo b/evibes/locale/kk_KZ/LC_MESSAGES/django.mo index 0fc354f2..47c1f925 100644 Binary files a/evibes/locale/kk_KZ/LC_MESSAGES/django.mo and b/evibes/locale/kk_KZ/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/kk_KZ/LC_MESSAGES/django.po b/evibes/locale/kk_KZ/LC_MESSAGES/django.po index 9a7d8f60..75d54335 100644 --- a/evibes/locale/kk_KZ/LC_MESSAGES/django.po +++ b/evibes/locale/kk_KZ/LC_MESSAGES/django.po @@ -5,9 +5,9 @@ # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -16,34 +16,30 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: evibes/settings/constance.py:18 +#: evibes/settings/constance.py:22 msgid "Name of the project" msgstr "" -#: evibes/settings/constance.py:19 +#: evibes/settings/constance.py:23 msgid "Frontend domain name" msgstr "" -#: evibes/settings/constance.py:20 +#: evibes/settings/constance.py:24 msgid "Base domain name" msgstr "" -#: evibes/settings/constance.py:21 +#: evibes/settings/constance.py:25 msgid "Name of the company" msgstr "" -#: evibes/settings/constance.py:22 +#: evibes/settings/constance.py:26 msgid "Address of the company" msgstr "" -#: evibes/settings/constance.py:23 +#: evibes/settings/constance.py:27 msgid "Phone number of the company" msgstr "" -#: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" - #: evibes/settings/constance.py:28 msgid "SMTP host" msgstr "" @@ -53,11 +49,11 @@ msgid "SMTP port" msgstr "" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" +msgid "Use TLS (0=No, 1=Yes)" msgstr "" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" +msgid "Use SSL (0=No, 1=Yes)" msgstr "" #: evibes/settings/constance.py:32 @@ -100,102 +96,66 @@ msgstr "" msgid "OpenAI API Key" msgstr "" -#: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" msgstr "" -#: evibes/settings/constance.py:46 +#: evibes/settings/constance.py:43 msgid "HTTP Proxy" msgstr "" -#: evibes/settings/constance.py:47 +#: evibes/settings/constance.py:44 msgid "Disable buy functionality" msgstr "" -#: evibes/settings/constance.py:50 +#: evibes/settings/constance.py:47 msgid "An entity for storing advertisiment data" msgstr "" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" msgstr "" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" +#: evibes/settings/constance.py:54 +msgid "General Options" msgstr "" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" msgstr "" diff --git a/evibes/locale/nl_NL/LC_MESSAGES/django.mo b/evibes/locale/nl_NL/LC_MESSAGES/django.mo index 0fc354f2..b51078fc 100644 Binary files a/evibes/locale/nl_NL/LC_MESSAGES/django.mo and b/evibes/locale/nl_NL/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/nl_NL/LC_MESSAGES/django.po b/evibes/locale/nl_NL/LC_MESSAGES/django.po index 9a7d8f60..60e90e40 100644 --- a/evibes/locale/nl_NL/LC_MESSAGES/django.po +++ b/evibes/locale/nl_NL/LC_MESSAGES/django.po @@ -1,201 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: nl-nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "Naam van het project" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "Frontend domeinnaam" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "Basis domeinnaam" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "Naam van het bedrijf" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "Adres van het bedrijf" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "Telefoonnummer van het bedrijf" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "SMTP host" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "SMTP poort" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "TLS gebruiken" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "SSL gebruiken" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "SMTP gebruikersnaam" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "SMTP wachtwoord" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "Het adres van de afzender van de e-mail" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "URL betalingsgateway" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "Betaal gateway token" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "Minimumbedrag betalingsgateway" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "Maximumbedrag betalingsgateway" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "Wisselkoers API sleutel" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "OpenStreetMap Nominatim API URL" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "OpenAI API sleutel" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "Abstracte API-sleutel" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "HTTP-proxy" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "Koopfunctie uitschakelen" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "Een entiteit voor het opslaan van adverteerdersgegevens" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "Een entiteit voor het opslaan van analytische gegevens" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "Algemene opties" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "E-mailopties" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "Opties voor betalingsgateways" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "Functies Opties" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "SEO Opties" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "Home" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "Winkelpui" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "GraphQL-documenten" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "Platform REST-documenten" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "B2B REST-documenten" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "Ondersteuning" diff --git a/evibes/locale/pl_PL/LC_MESSAGES/django.mo b/evibes/locale/pl_PL/LC_MESSAGES/django.mo index 0fc354f2..17cfa98f 100644 Binary files a/evibes/locale/pl_PL/LC_MESSAGES/django.mo and b/evibes/locale/pl_PL/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/pl_PL/LC_MESSAGES/django.po b/evibes/locale/pl_PL/LC_MESSAGES/django.po index 9a7d8f60..50f7619c 100644 --- a/evibes/locale/pl_PL/LC_MESSAGES/django.po +++ b/evibes/locale/pl_PL/LC_MESSAGES/django.po @@ -1,201 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: pl-pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "Nazwa projektu" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "Nazwa domeny frontendu" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "Nazwa domeny podstawowej" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "Nazwa firmy" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "Adres spółki" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "Numer telefonu firmy" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "Host SMTP" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "Port SMTP" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "Używanie TLS" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "Używanie protokołu SSL" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "Nazwa użytkownika SMTP" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "Hasło SMTP" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "Adres nadawcy wiadomości e-mail" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "Adres URL bramki płatności" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "Token bramki płatności" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "Minimalna kwota bramki płatności" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "Maksymalna kwota bramki płatności" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "Klucz API kursu wymiany" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "Adres URL interfejsu API OpenStreetMap Nominatim" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "Klucz API OpenAI" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "Abstrakcyjny klucz API" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "Serwer proxy HTTP" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "Wyłączenie funkcji kupowania" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "Jednostka do przechowywania danych reklamowych" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "Jednostka do przechowywania danych analitycznych" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "Opcje ogólne" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "Opcje e-mail" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "Opcje bramki płatności" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "Opcje funkcji" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "Opcje SEO" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "Strona główna" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "Witryna sklepowa" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "Dokumenty GraphQL" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "Dokumenty platformy REST" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "Dokumenty B2B REST" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "Wsparcie" diff --git a/evibes/locale/pt_BR/LC_MESSAGES/django.mo b/evibes/locale/pt_BR/LC_MESSAGES/django.mo index e7d918d9..8c3c4184 100644 Binary files a/evibes/locale/pt_BR/LC_MESSAGES/django.mo and b/evibes/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/pt_BR/LC_MESSAGES/django.po b/evibes/locale/pt_BR/LC_MESSAGES/django.po index b841007d..0dc4779e 100644 --- a/evibes/locale/pt_BR/LC_MESSAGES/django.po +++ b/evibes/locale/pt_BR/LC_MESSAGES/django.po @@ -1,202 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: pt-br\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "Nome do projeto" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "Nome de domínio de front-end" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "Nome de domínio básico" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "Nome da empresa" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "Endereço da empresa" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "Número de telefone da empresa" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "Host SMTP" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "Porta SMTP" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "Usar TLS" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "Usar SSL" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "Nome de usuário SMTP" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "Senha SMTP" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "O endereço do remetente do e-mail" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "URL do gateway de pagamento" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "Token de gateway de pagamento" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "Valor mínimo do gateway de pagamento" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "Valor máximo do gateway de pagamento" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "Chave da API de taxa de câmbio" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "URL da API do OpenStreetMap Nominatim" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "Chave da API da OpenAI" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "Chave abstrata da API" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "Proxy HTTP" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "Desativar a funcionalidade de compra" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "Uma entidade para armazenar dados de propaganda" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "Uma entidade para armazenar dados analíticos" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "Opções gerais" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "Opções de e-mail" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "Opções de gateway de pagamento" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "Opções de recursos" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "Opções de SEO" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "Início" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "Vitrine" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "Documentos do GraphQL" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "Documentos REST da plataforma" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "Documentos B2B REST" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "Suporte" diff --git a/evibes/locale/ro_RO/LC_MESSAGES/django.mo b/evibes/locale/ro_RO/LC_MESSAGES/django.mo index 0fc354f2..6f0b3b4b 100644 Binary files a/evibes/locale/ro_RO/LC_MESSAGES/django.mo and b/evibes/locale/ro_RO/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/ro_RO/LC_MESSAGES/django.po b/evibes/locale/ro_RO/LC_MESSAGES/django.po index 9a7d8f60..4fc0b953 100644 --- a/evibes/locale/ro_RO/LC_MESSAGES/django.po +++ b/evibes/locale/ro_RO/LC_MESSAGES/django.po @@ -1,201 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: ro-ro\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "Denumirea proiectului" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "Nume de domeniu Frontend" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "Numele domeniului de bază" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "Denumirea societății" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "Adresa societății" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "Numărul de telefon al societății" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "Gazdă SMTP" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "Portul SMTP" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "Utilizați TLS" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "Utilizați SSL" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "Nume utilizator SMTP" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "Parola SMTP" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "Adresa expeditorului e-mailurilor" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "URL-ul gateway-ului de plată" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "Token pentru gateway-ul de plată" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "Suma minimă a gateway-ului de plată" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "Suma maximă a gateway-ului de plată" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "Cheie API pentru rata de schimb" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "OpenStreetMap Nominatim API URL" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "Cheie API OpenAI" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "Cheie API abstractă" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "Proxy HTTP" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "Dezactivați funcționalitatea de cumpărare" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "O entitate pentru stocarea datelor privind publicitatea" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "O entitate pentru stocarea datelor analitice" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "Opțiuni generale" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "Opțiuni de e-mail" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "Opțiuni pentru portalul de plăți" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "Caracteristici Opțiuni" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "Opțiuni SEO" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "Acasă" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "Vitrină" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "Docuri GraphQL" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "Platforma REST Docs" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "Docuri B2B REST" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "Sprijin" diff --git a/evibes/locale/ru_RU/LC_MESSAGES/django.mo b/evibes/locale/ru_RU/LC_MESSAGES/django.mo index 0fc354f2..b70b4f28 100644 Binary files a/evibes/locale/ru_RU/LC_MESSAGES/django.mo and b/evibes/locale/ru_RU/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/ru_RU/LC_MESSAGES/django.po b/evibes/locale/ru_RU/LC_MESSAGES/django.po index 9a7d8f60..57270c24 100644 --- a/evibes/locale/ru_RU/LC_MESSAGES/django.po +++ b/evibes/locale/ru_RU/LC_MESSAGES/django.po @@ -1,201 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: ru-ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "Название проекта" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "Доменное имя фронтенд-приложения" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "Базовое доменное имя" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "Название компании" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "Адрес компании" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "Номер телефона компании" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "SMTP-хост" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "Порт SMTP" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "Используйте TLS" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "Используйте SSL" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "Имя пользователя SMTP" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "Пароль SMTP" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "Адрес отправителя электронного письма" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "URL-адрес платежного шлюза" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "Токен платежного шлюза" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "Минимальная сумма платежного шлюза" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "Максимальная сумма платежного шлюза" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "Ключ API обменного курса" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "URL-адрес API OpenStreetMap Nominatim" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "Ключ API OpenAI" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "Абстрактный ключ API" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "HTTP-прокси" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "Отключить функцию покупки" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "Устройство для хранения данных о рекламе" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "Сущность для хранения аналитических данных" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "Общие параметры" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "Параметры электронной почты" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "Варианты платежных шлюзов" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "Особенности Опции" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "Параметры SEO" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "Главная" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "Витрина" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "Документация по GraphQL" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "Документация по REST" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "Документация по B2B REST" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "Поддержка" diff --git a/evibes/locale/zh_Hans/LC_MESSAGES/django.mo b/evibes/locale/zh_Hans/LC_MESSAGES/django.mo index ed31f42b..ad32b734 100644 Binary files a/evibes/locale/zh_Hans/LC_MESSAGES/django.mo and b/evibes/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/evibes/locale/zh_Hans/LC_MESSAGES/django.po b/evibes/locale/zh_Hans/LC_MESSAGES/django.po index 1380a17d..5fc42118 100644 --- a/evibes/locale/zh_Hans/LC_MESSAGES/django.po +++ b/evibes/locale/zh_Hans/LC_MESSAGES/django.po @@ -1,202 +1,158 @@ -# EVIBES GETTEXT TRANSLATIONS -# Copyright (C) 2025 EGOR GORBUNOV -# This file is distributed under the same license as the EVIBES package. -# EGOR GORBUNOV , 2025. # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-18 08:39+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" -"Language: \n" +"Language: zh-hans\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: evibes/settings/constance.py:18 -msgid "Name of the project" -msgstr "" - -#: evibes/settings/constance.py:19 -msgid "Frontend domain name" -msgstr "" - -#: evibes/settings/constance.py:20 -msgid "Base domain name" -msgstr "" - -#: evibes/settings/constance.py:21 -msgid "Name of the company" -msgstr "" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: evibes/settings/constance.py:22 -msgid "Address of the company" -msgstr "" +msgid "Name of the project" +msgstr "项目名称" #: evibes/settings/constance.py:23 -msgid "Phone number of the company" -msgstr "" +msgid "Frontend domain name" +msgstr "前台域名" + +#: evibes/settings/constance.py:24 +msgid "Base domain name" +msgstr "基础域名" + +#: evibes/settings/constance.py:25 +msgid "Name of the company" +msgstr "公司名称" #: evibes/settings/constance.py:26 -msgid "Designates whether every product has one stock or not" -msgstr "" +msgid "Address of the company" +msgstr "公司地址" + +#: evibes/settings/constance.py:27 +msgid "Phone number of the company" +msgstr "公司电话号码" #: evibes/settings/constance.py:28 msgid "SMTP host" -msgstr "" +msgstr "SMTP 主机" #: evibes/settings/constance.py:29 msgid "SMTP port" -msgstr "" +msgstr "SMTP 端口" #: evibes/settings/constance.py:30 -msgid "Use TLS (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use TLS (0=No, 1=Yes)" +msgstr "使用 TLS" #: evibes/settings/constance.py:31 -msgid "Use SSL (Specify 0 for No and 1 for Yes)" -msgstr "" +msgid "Use SSL (0=No, 1=Yes)" +msgstr "使用 SSL" #: evibes/settings/constance.py:32 msgid "SMTP username" -msgstr "" +msgstr "SMTP 用户名" #: evibes/settings/constance.py:33 msgid "SMTP password" -msgstr "" +msgstr "SMTP 密码" #: evibes/settings/constance.py:34 msgid "Mail from option" -msgstr "" +msgstr "邮件发件人地址" #: evibes/settings/constance.py:35 msgid "Payment gateway URL" -msgstr "" +msgstr "付款网关 URL" #: evibes/settings/constance.py:36 msgid "Payment gateway token" -msgstr "" +msgstr "支付网关令牌" #: evibes/settings/constance.py:37 msgid "Payment gateway minimum amount" -msgstr "" +msgstr "支付网关最低金额" #: evibes/settings/constance.py:38 msgid "Payment gateway maximum amount" -msgstr "" +msgstr "支付网关最高限额" #: evibes/settings/constance.py:39 msgid "Exchange rate API key" -msgstr "" +msgstr "汇率 API 密钥" #: evibes/settings/constance.py:40 msgid "OpenStreetMap Nominatim API URL" -msgstr "" +msgstr "OpenStreetMap Nominatim API URL" #: evibes/settings/constance.py:41 msgid "OpenAI API Key" -msgstr "" +msgstr "OpenAI API 密钥" + +#: evibes/settings/constance.py:42 +msgid "Abstract API Key" +msgstr "抽象应用程序接口密钥" + +#: evibes/settings/constance.py:43 +msgid "HTTP Proxy" +msgstr "HTTP 代理服务器" #: evibes/settings/constance.py:44 -msgid "Abstract API Key, if empty - no Abstract features provided" -msgstr "" - -#: evibes/settings/constance.py:46 -msgid "HTTP Proxy" -msgstr "" +msgid "Disable buy functionality" +msgstr "禁用购买功能" #: evibes/settings/constance.py:47 -msgid "Disable buy functionality" -msgstr "" - -#: evibes/settings/constance.py:50 msgid "An entity for storing advertisiment data" -msgstr "" +msgstr "存储广告数据的实体" -#: evibes/settings/constance.py:55 +#: evibes/settings/constance.py:49 msgid "An entity for storing analytics data" -msgstr "" +msgstr "存储分析数据的实体" -#: evibes/settings/drf.py:49 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} B2B API is designed to " -"provide seamless integration for merchants selling a wide range of " -"electronics. Through this API, partnered merchants can manage products, " -"orders, and inventory with ease, while accessing real-time stock levels.\n" -"\n" -"## Key Features\n" -"- **Product Management:** Easily create, update, and manage your product " -"listings with detailed specifications.\n" -"- **Order Processing:** Handle bulk orders efficiently with streamlined " -"operations for merchants.\n" -"- **Inventory Management:** Keep track of stock levels in real-time, " -"ensuring smooth fulfillment.\n" -"- **Secure Transactions:** Secure and encrypted transactions to protect " -"sensitive business information.\n" -"- **Multi-Currency Support:** Expand your market reach with multi-currency " -"transactions.\n" -"- **Real-Time Notifications:** Stay updated with instant alerts on stock " -"changes and order statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via your merchant token. Include the token in " -"the `X-EVIBES-B2B-AUTH` header of your requests in the format `Bearer " -"`.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:54 +msgid "General Options" +msgstr "一般选项" -#: evibes/settings/drf.py:74 -msgid "" -"\n" -"Welcome to the {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} Platform API " -"documentation.\n" -"\n" -"The {CONSTANCE_CONFIG.get(\"PROJECT_NAME\")[0]} API is the central hub for " -"managing product listings, monitoring orders, and accessing analytics for " -"your electronics store. It provides RESTful endpoints for managing your " -"store’s backend operations and includes both REST and GraphQL options.\n" -"\n" -"## Key Features\n" -"- **Product Catalog:** Manage product details, pricing, and availability.\n" -"- **Order Management:** Access detailed order information and process " -"customer requests efficiently.\n" -"- **User Roles & Permissions:** Set user roles and permissions for internal " -"management.\n" -"- **Custom Integrations:** Connect your system with external platforms " -"through powerful APIs.\n" -"- **Detailed Reporting:** Generate comprehensive reports on orders, sales " -"performance, and product data.\n" -"- **Real-Time Data:** Get live updates on inventory, pricing, and order " -"statuses.\n" -"\n" -"## Authentication\n" -"- Authentication is handled via JWT tokens. Include the token in the `X-" -"EVIBES-AUTH` header of your requests in the format `Bearer `.\n" -"- Access token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 60 if not DEBUG else 3600} {\"minutes\" if not DEBUG else " -"\"hours\"}.\n" -"- Refresh token lifetime is {SIMPLE_JWT.get(\"ACCESS_TOKEN_LIFETIME\")." -"total_seconds() // 3600} hours.\n" -"- Refresh tokens are automatically invalidated after usage.\n" -"\n" -"## I18N\n" -"- Apply an `Accept-Language` header to use non-default language. A list of " -"all languages is available at `/app/languages/`.\n" -"\n" -"## Version\n" -"Current API version: {EVIBES_VERSION}\n" -msgstr "" +#: evibes/settings/constance.py:62 +msgid "Email Options" +msgstr "电子邮件选项" + +#: evibes/settings/constance.py:71 +msgid "Payment Gateway Options" +msgstr "支付网关选项" + +#: evibes/settings/constance.py:78 +msgid "Features Options" +msgstr "功能选项" + +#: evibes/settings/constance.py:85 +msgid "SEO Options" +msgstr "搜索引擎优化选项" + +#: evibes/settings/jazzmin.py:20 +msgid "Home" +msgstr "首页" + +#: evibes/settings/jazzmin.py:21 +msgid "Storefront" +msgstr "店面" + +#: evibes/settings/jazzmin.py:24 +msgid "GraphQL Docs" +msgstr "GraphQL 文档" + +#: evibes/settings/jazzmin.py:29 +msgid "Platform REST Docs" +msgstr "平台 REST 文档" + +#: evibes/settings/jazzmin.py:34 +msgid "B2B REST Docs" +msgstr "B2B REST 文档" + +#: evibes/settings/jazzmin.py:38 +msgid "Support" +msgstr "支持" diff --git a/evibes/middleware.py b/evibes/middleware.py index 56e21545..b411eb05 100644 --- a/evibes/middleware.py +++ b/evibes/middleware.py @@ -4,7 +4,7 @@ from os import getenv from constance import config from django.contrib.auth.models import AnonymousUser -from django.core.exceptions import BadRequest, DisallowedHost +from django.core.exceptions import BadRequest, DisallowedHost, PermissionDenied, ValidationError from django.http import HttpResponseForbidden from django.middleware.common import CommonMiddleware from django.middleware.locale import LocaleMiddleware @@ -16,7 +16,7 @@ from sentry_sdk import capture_exception from evibes.settings import DEBUG -logger = logging.getLogger("django.request") +logger = logging.getLogger("django") class CustomCommonMiddleware(CommonMiddleware): @@ -95,12 +95,21 @@ class BlockInvalidHostMiddleware: # noinspection PyShadowingBuiltins class GrapheneLoggingErrorsDebugMiddleware: + WARNING_ONLY_ERRORS = [ + BadRequest, + PermissionDenied, + DisallowedHost, + ValidationError, + ] + def resolve(self, next, root, info, **args): try: return next(root, info, **args) except Exception as e: - logger.error("Error occurred in GraphQL execution:", exc_info=True) - if bool(int(getenv("DEBUG"))): + if any(isinstance(e, error_type) for error_type in self.WARNING_ONLY_ERRORS): + logger.warning(str(e)) + else: + logger.error(str(e)) logger.error(traceback.format_exc()) - capture_exception(e) + capture_exception(e) raise e diff --git a/evibes/models.png b/evibes/models.png new file mode 100644 index 00000000..5c2377e5 Binary files /dev/null and b/evibes/models.png differ diff --git a/evibes/pagination.py b/evibes/pagination.py index be486861..99a9bd17 100644 --- a/evibes/pagination.py +++ b/evibes/pagination.py @@ -10,9 +10,9 @@ class CustomPagination(PageNumberPagination): { "links": {"forward": self.get_next_link(), "backward": self.get_previous_link()}, "counts": { - "total_pages": None or self.page.paginator.num_pages, # type: ignore - "page_size": None or self.page_size, # type: ignore - "total_items": None or self.page.paginator.count, # type: ignore + "total_pages": None or self.page.paginator.num_pages, # type: ignore [union-attr] + "page_size": None or self.page_size, + "total_items": None or self.page.paginator.count, # type: ignore [union-attr] }, "data": data, } diff --git a/evibes/settings/__init__.py b/evibes/settings/__init__.py index 74696a6d..86adbb63 100644 --- a/evibes/settings/__init__.py +++ b/evibes/settings/__init__.py @@ -2,7 +2,6 @@ from .caches import * # noqa: F403 from .celery import * # noqa: F403 from .constance import * # noqa: F403 from .csp import * # noqa: F403 -from .daisy import * # noqa: F403 from .database import * # noqa: F403 from .dbbackup import * # noqa: F403 from .drf import * # noqa: F403 @@ -10,5 +9,6 @@ from .elasticsearch import * # noqa: F403 from .emailing import * # noqa: F403 from .extensions import * # noqa: F403 from .graphene import * # noqa: F403 +from .jazzmin import * # noqa: F403 from .logconfig import * # noqa: F403 from .summernote import * # noqa: F403 diff --git a/evibes/settings/base.py b/evibes/settings/base.py index 300a0b66..651e850c 100644 --- a/evibes/settings/base.py +++ b/evibes/settings/base.py @@ -1,15 +1,15 @@ import logging -from os import getenv +from os import getenv, name from pathlib import Path -EVIBES_VERSION = "2.8.10" +EVIBES_VERSION = "2.9.2" BASE_DIR = Path(__file__).resolve().parent.parent.parent SECRET_KEY = getenv("SECRET_KEY", "SUPER_SECRET_KEY") DEBUG = bool(int(getenv("DEBUG", "1"))) -ALLOWED_HOSTS = { +ALLOWED_HOSTS: set = { "app", "worker", "beat", @@ -27,9 +27,9 @@ else: for entry in getenv("ALLOWED_HOSTS", "").split(" "): ALLOWED_HOSTS.add(entry) -ALLOWED_HOSTS = tuple(ALLOWED_HOSTS) # type: ignore +ALLOWED_HOSTS: tuple = tuple(ALLOWED_HOSTS) -CSRF_TRUSTED_ORIGINS = { +CSRF_TRUSTED_ORIGINS: set = { "http://127.0.0.1", "http://api.localhost", "http://b2b.localhost", @@ -38,12 +38,12 @@ CSRF_TRUSTED_ORIGINS = { for entry in getenv("CSRF_TRUSTED_ORIGINS", "").split(" "): CSRF_TRUSTED_ORIGINS.add(entry) -CSRF_TRUSTED_ORIGINS = tuple(CSRF_TRUSTED_ORIGINS) # type: ignore +CSRF_TRUSTED_ORIGINS: tuple = tuple(CSRF_TRUSTED_ORIGINS) if DEBUG: CORS_ALLOW_ALL_ORIGINS = True else: - CORS_ALLOWED_ORIGINS = { + CORS_ALLOWED_ORIGINS: set = { "http://127.0.0.1", "http://api.localhost", "http://b2b.localhost", @@ -51,7 +51,7 @@ else: for entry in getenv("CORS_ALLOWED_ORIGINS", "").split(" "): CORS_ALLOWED_ORIGINS.add(entry) - CORS_ALLOWED_ORIGINS = tuple(CORS_ALLOWED_ORIGINS) # type: ignore + CORS_ALLOWED_ORIGINS: tuple = tuple(CORS_ALLOWED_ORIGINS) CORS_ALLOW_METHODS = ( "DELETE", @@ -96,9 +96,10 @@ SITE_ID: int = 1 INSTALLED_APPS: list[str] = [ "django_prometheus", "constance", - "django_daisy", + "jazzmin", "modeltranslation", "django.contrib.admin", + "django.contrib.admindocs", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", @@ -112,8 +113,11 @@ INSTALLED_APPS: list[str] = [ "health_check.cache", "health_check.storage", "health_check.contrib.migrations", + "health_check.contrib.celery_ping", "health_check.contrib.psutil", + "health_check.contrib.redis", "health_check.contrib.db_heartbeat", + "health_check.contrib.mail", "cacheops", "django_hosts", "django_celery_beat", @@ -152,6 +156,7 @@ MIDDLEWARE: list[str] = [ "django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", + "django.contrib.admindocs.middleware.XViewMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", "evibes.middleware.CustomLocaleMiddleware", "django_hosts.middleware.HostsResponseMiddleware", @@ -225,7 +230,7 @@ CURRENCIES: tuple[tuple[str, str], ...] = ( ("zh-hans", "CNY"), ) -CURRENCY_CODE: str | None = dict(CURRENCIES).get(LANGUAGE_CODE) +CURRENCY_CODE: str = dict(CURRENCIES).get(LANGUAGE_CODE) # type: ignore [assignment] MODELTRANSLATION_FALLBACK_LANGUAGES: tuple = (LANGUAGE_CODE, "en-us", "de-de") @@ -267,6 +272,7 @@ APPEND_SLASH: bool = True ROOT_HOSTCONF: str = "evibes.hosts" DEFAULT_HOST: str = "api" REDIS_PASSWORD: str = getenv("REDIS_PASSWORD", default="") +REDIS_URL: str = f"redis://:{REDIS_PASSWORD}@redis:6379/0" INTERNAL_IPS: list[str] = [ "127.0.0.1", @@ -279,28 +285,32 @@ if getenv("SENTRY_DSN"): from sentry_sdk.integrations.logging import LoggingIntegration from sentry_sdk.integrations.redis import RedisIntegration - ignore_errors: list[str] = [ - "django.http.response.Http404", - "django.core.exceptions.PermissionDenied", - "django.core.exceptions.BadRequest", - "django.db.utils.OperationalError", - "billiard.exceptions.SoftTimeLimitExceeded", # This is a handled exception - "billiard.exceptions.WorkerLostError", # This is a handled exception - "core.models.Attribute.DoesNotExist", - "core.models.AttributeGroup.DoesNotExist", - "core.models.AttributeValue.DoesNotExist", - "core.models.Product.DoesNotExist", - "core.models.Category.DoesNotExist", - "core.models.Brand.DoesNotExist", - "core.models.Stock.DoesNotExist", - "core.models.ProductImage.DoesNotExist", - "blog.models.Post.DoesNotExist", - ] + def scrub_sensitive(data): + if isinstance(data, dict): + cleaned = {} + for key, value in data.items(): + if key.lower() in ("password", "confirm_password"): + cleaned[key] = "[FILTERED]" + else: + cleaned[key] = scrub_sensitive(value) + return cleaned + if isinstance(data, list): + return [scrub_sensitive(item) for item in data] + return data + + def before_send(event, hint): + if hint: + pass + request = event.get("request", {}) + if "data" in request: + request["data"] = scrub_sensitive(request["data"]) + event["request"] = request + return event + + ignore_errors: list[str] = [] sentry_sdk.init( dsn=getenv("SENTRY_DSN"), - traces_sample_rate=1.0 if DEBUG else 0.2, - profiles_sample_rate=1.0 if DEBUG else 0.1, integrations=[ DjangoIntegration(), LoggingIntegration(level=logging.INFO, event_level=logging.ERROR), @@ -308,9 +318,13 @@ if getenv("SENTRY_DSN"): RedisIntegration(), ], environment="development" if DEBUG else "production", - debug=False, release=f"evibes@{EVIBES_VERSION}", + traces_sample_rate=1.0 if DEBUG else 0.2, + profiles_sample_rate=1.0 if DEBUG else 0.1, + max_request_body_size="always", + before_send=before_send, ignore_errors=ignore_errors, + debug=False, ) SESSION_COOKIE_HTTPONLY: bool = True @@ -332,3 +346,7 @@ STORAGES: dict[str, dict[str, str | int | bool | None]] = { "BACKEND": "django.core.files.storage.FileSystemStorage", }, } + +if name == "nt": + GDAL_LIBRARY_PATH = r"C:\OSGeo4W\bin\gdal311.dll" + GEOS_LIBRARY_PATH = r"C:\OSGeo4W\bin\geos_c.dll" diff --git a/evibes/settings/celery.py b/evibes/settings/celery.py index 94f0c08b..6ff53d01 100644 --- a/evibes/settings/celery.py +++ b/evibes/settings/celery.py @@ -1,9 +1,26 @@ from datetime import timedelta -from evibes.settings import REDIS_PASSWORD +from evibes.settings.base import REDIS_PASSWORD, TIME_ZONE -CELERY_BROKER_URL = f"redis://:{REDIS_PASSWORD + '@'}redis:6379/0" -CELERY_RESULT_BACKEND = f"redis://:{REDIS_PASSWORD + '@'}redis:6379/0" +CELERY_ENABLE_UTC = False +CELERY_TIMEZONE = TIME_ZONE + +CELERY_BROKER_URL = f"redis://:{REDIS_PASSWORD}@redis:6379/0" + +CELERY_BROKER_HEARTBEAT = 10 +CELERY_BROKER_HEARTBEAT_CHECKRATE = 2 + +CELERY_BROKER_POOL_LIMIT = 10 +CELERY_BROKER_TRANSPORT_OPTIONS = { + "visibility_timeout": 3600, + "retry_policy": {"interval_start": 0.1, "interval_step": 0.2, "max_retries": 5}, + "socket_keepalive": True, + "socket_timeout": 30, + "socket_connect_timeout": 30, + "retry_on_timeout": True, +} + +CELERY_RESULT_BACKEND = CELERY_BROKER_URL CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers.DatabaseScheduler" @@ -11,21 +28,26 @@ CELERY_BEAT_SCHEDULE = { "update_products_task": { "task": "core.tasks.update_products_task", "schedule": timedelta(minutes=60), + "options": {"queue": "stock_updater"}, }, "update_orderproducts_task": { "task": "core.tasks.update_orderproducts_task", "schedule": timedelta(minutes=1), + "options": {"queue": "default"}, }, "set_default_caches_task": { "task": "core.tasks.set_default_caches_task", "schedule": timedelta(hours=4), + "options": {"queue": "default"}, }, "remove_stale_product_images": { "task": "core.tasks.remove_stale_product_images", "schedule": timedelta(days=1), + "options": {"queue": "default"}, }, "process_promotions": { "task": "core.tasks.process_promotions", "schedule": timedelta(hours=2), + "options": {"queue": "default"}, }, } diff --git a/evibes/settings/constance.py b/evibes/settings/constance.py index e108ced7..69b12293 100644 --- a/evibes/settings/constance.py +++ b/evibes/settings/constance.py @@ -1,8 +1,11 @@ -from django.utils.translation import gettext_lazy as _ +from collections import OrderedDict + +from django.utils.translation import gettext_lazy as _, gettext_noop from evibes.settings.base import getenv -CONSTANCE_BACKEND = "constance.backends.database.DatabaseBackend" # Or "constance.backends.redis.RedisBackend" +CONSTANCE_BACKEND = "constance.backends.database.DatabaseBackend" +CONSTANCE_SUPERUSER_ONLY = False CONSTANCE_ADDITIONAL_FIELDS = { "json": [ @@ -14,48 +17,78 @@ CONSTANCE_ADDITIONAL_FIELDS = { ], } -CONSTANCE_CONFIG = { - "PROJECT_NAME": (getenv("EVIBES_PROJECT_NAME"), _("Name of the project")), - "FRONTEND_DOMAIN": (getenv("EVIBES_FRONTEND_DOMAIN"), _("Frontend domain name")), - "BASE_DOMAIN": (getenv("EVIBES_BASE_DOMAIN"), _("Base domain name")), - "COMPANY_NAME": (getenv("COMPANY_NAME"), _("Name of the company")), - "COMPANY_ADDRESS": (getenv("COMPANY_ADDRESS"), _("Address of the company")), - "COMPANY_PHONE_NUMBER": (getenv("COMPANY_PHONE_NUMBER"), _("Phone number of the company")), - "STOCKS_ARE_SINGLE": ( - getenv("STOCKS_ARE_SINGLE", True), - _("Designates whether every product has one stock or not"), - ), - "EMAIL_HOST": (getenv("EMAIL_HOST", "smtp.404.org"), _("SMTP host")), - "EMAIL_PORT": (int(getenv("EMAIL_PORT", "465")), _("SMTP port")), - "EMAIL_USE_TLS": (bool(int(getenv("EMAIL_USE_TLS", 0))), _("Use TLS (Specify 0 for No and 1 for Yes)")), - "EMAIL_USE_SSL": (bool(int(getenv("EMAIL_USE_SSL", 1))), _("Use SSL (Specify 0 for No and 1 for Yes)")), - "EMAIL_HOST_USER": (getenv("EMAIL_HOST_USER", "no-user@fix.this"), _("SMTP username")), - "EMAIL_HOST_PASSWORD": (getenv("EMAIL_HOST_PASSWORD", "SUPERsecretPASSWORD"), _("SMTP password")), - "EMAIL_FROM": (getenv("EMAIL_FROM", "eVibes"), _("Mail from option")), - "PAYMENT_GATEWAY_URL": (getenv("PAYMENT_GATEWAY_URL", "http://404.org"), _("Payment gateway URL")), - "PAYMENT_GATEWAY_TOKEN": (getenv("PAYMENT_GATEWAY_TOKEN", "example token"), _("Payment gateway token")), - "PAYMENT_GATEWAY_MINIMUM": (getenv("PAYMENT_GATEWAY_MINIMUM", 5.0), _("Payment gateway minimum amount")), - "PAYMENT_GATEWAY_MAXIMUM": (getenv("PAYMENT_GATEWAY_MAXIMUM", 500.0), _("Payment gateway maximum amount")), - "EXCHANGE_RATE_API_KEY": (getenv("EXCHANGE_RATE_API_KEY", "example token"), _("Exchange rate API key")), - "NOMINATIM_URL": (getenv("NOMINATIM_URL", ""), _("OpenStreetMap Nominatim API URL")), - "OPENAI_API_KEY": (getenv("OPENAI_API_KEY", "example key"), _("OpenAI API Key")), - "ABSTRACT_API_KEY": ( - getenv("ABSTRACT_API_KEY", "example key"), - _("Abstract API Key, if empty - no Abstract features provided"), - ), - "HTTP_PROXY": (getenv("DJANGO_HTTP_PROXY", "http://username:password@proxy_address:port"), _("HTTP Proxy")), - "DISABLED_COMMERCE": (getenv("DISABLED_COMMERCE", False), _("Disable buy functionality")), - "ADVERTISEMENT_DATA": ( - getenv("EVIBES_ADVERTISEMENT_DATA", ""), - _("An entity for storing advertisiment data"), - "json", - ), - "ANALYTICS_DATA": ( - getenv("EVIBES_ANALYTICS_DATA", ""), - _("An entity for storing analytics data"), - "json", - ), -} +CONSTANCE_CONFIG = OrderedDict( + [ + ("PROJECT_NAME", (getenv("EVIBES_PROJECT_NAME"), _("Name of the project"))), + ("FRONTEND_DOMAIN", (getenv("EVIBES_FRONTEND_DOMAIN"), _("Frontend domain name"))), + ("BASE_DOMAIN", (getenv("EVIBES_BASE_DOMAIN"), _("Base domain name"))), + ("COMPANY_NAME", (getenv("COMPANY_NAME"), _("Name of the company"))), + ("COMPANY_ADDRESS", (getenv("COMPANY_ADDRESS"), _("Address of the company"))), + ("COMPANY_PHONE_NUMBER", (getenv("COMPANY_PHONE_NUMBER"), _("Phone number of the company"))), + ("EMAIL_HOST", (getenv("EMAIL_HOST", "smtp.404.org"), _("SMTP host"))), + ("EMAIL_PORT", (int(getenv("EMAIL_PORT", "465")), _("SMTP port"))), + ("EMAIL_USE_TLS", (bool(int(getenv("EMAIL_USE_TLS", 0))), _("Use TLS (0=No, 1=Yes)"))), + ("EMAIL_USE_SSL", (bool(int(getenv("EMAIL_USE_SSL", 1))), _("Use SSL (0=No, 1=Yes)"))), + ("EMAIL_HOST_USER", (getenv("EMAIL_HOST_USER", "no-user@fix.this"), _("SMTP username"))), + ("EMAIL_HOST_PASSWORD", (getenv("EMAIL_HOST_PASSWORD", "SUPERsecretPASSWORD"), _("SMTP password"))), + ("EMAIL_FROM", (getenv("EMAIL_FROM", "eVibes"), _("Mail from option"))), + ("PAYMENT_GATEWAY_URL", (getenv("PAYMENT_GATEWAY_URL", "http://404.org"), _("Payment gateway URL"))), + ("PAYMENT_GATEWAY_TOKEN", (getenv("PAYMENT_GATEWAY_TOKEN", "example token"), _("Payment gateway token"))), + ("PAYMENT_GATEWAY_MINIMUM", (getenv("PAYMENT_GATEWAY_MINIMUM", 5.0), _("Payment gateway minimum amount"))), + ("PAYMENT_GATEWAY_MAXIMUM", (getenv("PAYMENT_GATEWAY_MAXIMUM", 500.0), _("Payment gateway maximum amount"))), + ("EXCHANGE_RATE_API_KEY", (getenv("EXCHANGE_RATE_API_KEY", "example token"), _("Exchange rate API key"))), + ("NOMINATIM_URL", (getenv("NOMINATIM_URL", ""), _("OpenStreetMap Nominatim API URL"))), + ("OPENAI_API_KEY", (getenv("OPENAI_API_KEY", "example key"), _("OpenAI API Key"))), + ("ABSTRACT_API_KEY", (getenv("ABSTRACT_API_KEY", "example key"), _("Abstract API Key"))), + ("HTTP_PROXY", (getenv("DJANGO_HTTP_PROXY", "http://username:password@proxy_address:port"), _("HTTP Proxy"))), + ("DISABLED_COMMERCE", (getenv("DISABLED_COMMERCE", False), _("Disable buy functionality"))), + ( + "ADVERTISEMENT_DATA", + (getenv("EVIBES_ADVERTISEMENT_DATA", ""), _("An entity for storing advertisiment data"), "json"), + ), + ("ANALYTICS_DATA", (getenv("EVIBES_ANALYTICS_DATA", ""), _("An entity for storing analytics data"), "json")), + ] +) + +CONSTANCE_CONFIG_FIELDSETS = OrderedDict( + { + gettext_noop("General Options"): ( + "PROJECT_NAME", + "FRONTEND_DOMAIN", + "BASE_DOMAIN", + "COMPANY_NAME", + "COMPANY_ADDRESS", + "COMPANY_PHONE_NUMBER", + ), + gettext_noop("Email Options"): ( + "EMAIL_HOST", + "EMAIL_PORT", + "EMAIL_USE_TLS", + "EMAIL_USE_SSL", + "EMAIL_HOST_USER", + "EMAIL_HOST_PASSWORD", + "EMAIL_FROM", + ), + gettext_noop("Payment Gateway Options"): ( + "PAYMENT_GATEWAY_URL", + "PAYMENT_GATEWAY_TOKEN", + "EXCHANGE_RATE_API_KEY", + "PAYMENT_GATEWAY_MINIMUM", + "PAYMENT_GATEWAY_MAXIMUM", + ), + gettext_noop("Features Options"): ( + "DISABLED_COMMERCE", + "NOMINATIM_URL", + "OPENAI_API_KEY", + "ABSTRACT_API_KEY", + "HTTP_PROXY", + ), + gettext_noop("SEO Options"): ( + "ADVERTISEMENT_DATA", + "ANALYTICS_DATA", + ), + } +) EXPOSABLE_KEYS = [ "PROJECT_NAME", diff --git a/evibes/settings/daisy.py b/evibes/settings/daisy.py deleted file mode 100644 index 7e4c8192..00000000 --- a/evibes/settings/daisy.py +++ /dev/null @@ -1,38 +0,0 @@ -from evibes.settings.base import EVIBES_VERSION -from evibes.settings.constance import CONSTANCE_CONFIG - -DAISY_SETTINGS: dict = { - "SITE_LOGO": "/static/favicon.ico", - "EXTRA_STYLES": [ - f"https://api.{CONSTANCE_CONFIG.get('BASE_DOMAIN')[0]}/static/css/constance.css", # type: ignore - ], - "EXTRA_SCRIPTS": [], - "SHOW_CHANGELIST_FILTER": True, - "DONT_SUPPORT_ME": True, - "SIDEBAR_FOOTNOTE": f"eVibes {EVIBES_VERSION} by Wiseless", - "LOAD_FULL_STYLES": True, - "APPS_REORDER": { - "django_celery_results": { - "hide": True, - "app": "django_celery_results", - }, - "django_celery_beat": { - "icon": "fa fa-solid fa-timeline", - "hide": False, - "app": "django_celery_beat", - "priority": 1, - }, - "django_mailbox": { - "icon": "fa fa-solid fa-envelope", - "hide": False, - "app": "django_mailbox", - "priority": 2, - }, - "django_summernote": { - "icon": "fa fa-solid fa-note-sticky", - "hide": False, - "app": "django_summernote", - "priority": 3, - }, - }, -} diff --git a/evibes/settings/database.py b/evibes/settings/database.py index 3036c70c..80a8858f 100644 --- a/evibes/settings/database.py +++ b/evibes/settings/database.py @@ -1,11 +1,11 @@ -from evibes.settings.base import * # noqa: F403 +from os import getenv DATABASES = { "default": { "ENGINE": "django_prometheus.db.backends.postgis", - "NAME": getenv("POSTGRES_DB"), # noqa: F405 - "USER": getenv("POSTGRES_USER"), # noqa: F405 - "PASSWORD": getenv("POSTGRES_PASSWORD"), # noqa: F405 + "NAME": getenv("POSTGRES_DB"), + "USER": getenv("POSTGRES_USER"), + "PASSWORD": getenv("POSTGRES_PASSWORD"), "HOST": "database", "PORT": 5432, } diff --git a/evibes/settings/dbbackup.py b/evibes/settings/dbbackup.py index fa86b908..fca73a7e 100644 --- a/evibes/settings/dbbackup.py +++ b/evibes/settings/dbbackup.py @@ -1,4 +1,5 @@ -from evibes.settings.base import getenv +from os import getenv +from django.core.exceptions import ImproperlyConfigured DBBACKUP_CONNECTORS = { "default": { @@ -8,21 +9,44 @@ DBBACKUP_CONNECTORS = { } } -if getenv("DBBACKUP_SFTP_HOST") and getenv("DBBACKUP_SFTP_USER") and getenv("DBBACKUP_SFTP_PASS"): - DBBACKUP_STORAGE = "storages.backends.sftpstorage.SFTPStorage" - DBBACKUP_STORAGE_OPTIONS = { - "host": getenv("DBBACKUP_SFTP_HOST"), - "root_path": "/db_backups/", - "params": { - "username": getenv("DBBACKUP_SFTP_USER"), - "password": getenv("DBBACKUP_SFTP_PASS"), - "allow_agent": False, - "look_for_keys": False, - }, - "interactive": False, - "file_mode": 0o600, - "dir_mode": 0o700, - } +if getenv("DBBACKUP_HOST") and getenv("DBBACKUP_USER") and getenv("DBBACKUP_PASS"): + dbbackup_server_type = getenv("DBBACKUP_TYPE", "sftp") + project_name = getenv("EVIBES_PROJECT_NAME", "evibes_common").lower().replace(" ", "_") + + raw_path = getenv("DBBACKUP_PATH", f"/backups/{project_name}/") + cleaned = raw_path.strip("/") + remote_dir = f"{cleaned}/" + + match dbbackup_server_type: + case "sftp": + DBBACKUP_STORAGE = "storages.backends.sftpstorage.SFTPStorage" + DBBACKUP_STORAGE_OPTIONS = { + "host": getenv("DBBACKUP_HOST"), + "root_path": f"/{remote_dir}", + "params": { + "username": getenv("DBBACKUP_USER"), + "password": getenv("DBBACKUP_PASS"), + "allow_agent": False, + "look_for_keys": False, + }, + "interactive": False, + "file_mode": 0o600, + "dir_mode": 0o700, + } + + case "ftp": + DBBACKUP_STORAGE = "evibes.ftpstorage.AbsoluteFTPStorage" + DBBACKUP_STORAGE_OPTIONS = { + "location": ( + f"ftp://{getenv('DBBACKUP_USER')}:{getenv('DBBACKUP_PASS')}@{getenv('DBBACKUP_HOST')}:21/{raw_path}" + ), + } + + case _: + raise ImproperlyConfigured(f"Invalid DBBACKUP_TYPE: {dbbackup_server_type}") + else: DBBACKUP_STORAGE = "django.core.files.storage.FileSystemStorage" - DBBACKUP_STORAGE_OPTIONS = {"location": "/app/db_backups/"} + DBBACKUP_STORAGE_OPTIONS = { + "location": "/app/backups/", + } diff --git a/evibes/settings/drf.py b/evibes/settings/drf.py index 393acec0..afd4ab65 100644 --- a/evibes/settings/drf.py +++ b/evibes/settings/drf.py @@ -1,9 +1,7 @@ -# mypy: ignore-errors from datetime import timedelta +from os import getenv -from django.utils.translation import gettext_lazy as _ - -from evibes.settings.base import * # noqa: F403 +from evibes.settings.base import DEBUG, EVIBES_VERSION, SECRET_KEY from evibes.settings.constance import CONSTANCE_CONFIG REST_FRAMEWORK: dict = { @@ -21,6 +19,8 @@ REST_FRAMEWORK: dict = { "DEFAULT_PARSER_CLASSES": ( "djangorestframework_camel_case.parser.CamelCaseJSONParser", "djangorestframework_camel_case.parser.CamelCaseMultiPartParser", + "rest_framework.parsers.FormParser", + "rest_framework.parsers.MultiPartParser", "rest_framework_xml.parsers.XMLParser", "rest_framework_yaml.parsers.YAMLParser", ), @@ -45,11 +45,15 @@ SIMPLE_JWT: dict[str, timedelta | str | bool] = { "AUTH_HEADER_NAME": "HTTP_X_EVIBES_AUTH", } -# type: ignore -SPECTACULAR_B2B_DESCRIPTION = _(f""" -Welcome to the {CONSTANCE_CONFIG.get("PROJECT_NAME")[0]} B2B API documentation. +SPECTACULAR_B2B_DESCRIPTION = ( # type: ignore [index] + f""" +Welcome to the { + CONSTANCE_CONFIG.get("PROJECT_NAME")[0] # type: ignore [index] + } B2B API documentation. -The {CONSTANCE_CONFIG.get("PROJECT_NAME")[0]} B2B API is designed to provide seamless integration for merchants selling a wide range of electronics. Through this API, partnered merchants can manage products, orders, and inventory with ease, while accessing real-time stock levels. +The { + CONSTANCE_CONFIG.get("PROJECT_NAME")[0] # type: ignore [index] + } B2B API is designed to provide seamless integration for merchants selling a wide range of electronics. Through this API, partnered merchants can manage products, orders, and inventory with ease, while accessing real-time stock levels. ## Key Features - **Product Management:** Easily create, update, and manage your product listings with detailed specifications. @@ -67,14 +71,17 @@ The {CONSTANCE_CONFIG.get("PROJECT_NAME")[0]} B2B API is designed to provide sea ## Version Current API version: {EVIBES_VERSION} -""") # noqa: E501, F405 +""" +) # noqa: E501, F405 -# type: ignore -# noinspection Mypy -SPECTACULAR_PLATFORM_DESCRIPTION = _(f""" -Welcome to the {CONSTANCE_CONFIG.get("PROJECT_NAME")[0]} Platform API documentation. +SPECTACULAR_PLATFORM_DESCRIPTION = f""" +Welcome to the { + CONSTANCE_CONFIG.get("PROJECT_NAME")[0] # type: ignore [index] +} Platform API documentation. -The {CONSTANCE_CONFIG.get("PROJECT_NAME")[0]} API is the central hub for managing product listings, monitoring orders, and accessing analytics for your electronics store. It provides RESTful endpoints for managing your store’s backend operations and includes both REST and GraphQL options. +The { + CONSTANCE_CONFIG.get("PROJECT_NAME")[0] # type: ignore [index] +} API is the central hub for managing product listings, monitoring orders, and accessing analytics for your electronics store. It provides RESTful endpoints for managing your store’s backend operations and includes both REST and GraphQL options. ## Key Features - **Product Catalog:** Manage product details, pricing, and availability. @@ -86,8 +93,12 @@ The {CONSTANCE_CONFIG.get("PROJECT_NAME")[0]} API is the central hub for managin ## Authentication - Authentication is handled via JWT tokens. Include the token in the `X-EVIBES-AUTH` header of your requests in the format `Bearer `. -- Access token lifetime is {SIMPLE_JWT.get("ACCESS_TOKEN_LIFETIME").total_seconds() // 60 if not DEBUG else 3600} {"minutes" if not DEBUG else "hours"}. -- Refresh token lifetime is {SIMPLE_JWT.get("ACCESS_TOKEN_LIFETIME").total_seconds() // 3600} hours. +- Access token lifetime is { + SIMPLE_JWT.get("ACCESS_TOKEN_LIFETIME").total_seconds() // 60 if not DEBUG else 3600 # type: ignore [union-attr] +} {"minutes" if not DEBUG else "hours"}. +- Refresh token lifetime is { + SIMPLE_JWT.get("REFRESH_TOKEN_LIFETIME").total_seconds() // 3600 # type: ignore [union-attr] +} hours. - Refresh tokens are automatically invalidated after usage. ## I18N @@ -95,10 +106,10 @@ The {CONSTANCE_CONFIG.get("PROJECT_NAME")[0]} API is the central hub for managin ## Version Current API version: {EVIBES_VERSION} -""") # noqa: E501, F405 +""" # noqa: E501, F405 SPECTACULAR_PLATFORM_SETTINGS = { - "TITLE": f"{CONSTANCE_CONFIG.get('PROJECT_NAME')[0]} API", + "TITLE": f"{CONSTANCE_CONFIG.get('PROJECT_NAME')[0]} API", # type: ignore [index] "DESCRIPTION": SPECTACULAR_PLATFORM_DESCRIPTION, "VERSION": EVIBES_VERSION, # noqa: F405 "TOS": "https://wiseless.xyz/evibes/terms-of-service", @@ -136,7 +147,7 @@ SPECTACULAR_PLATFORM_SETTINGS = { }, "SERVERS": [ { - "url": f"https://api.{CONSTANCE_CONFIG.get('BASE_DOMAIN')[0]}/", + "url": f"https://api.{CONSTANCE_CONFIG.get('BASE_DOMAIN')[0]}/", # type: ignore [index] "description": "Production Server", }, {"url": "http://api.localhost:8000/", "description": "Development Server"}, @@ -150,7 +161,7 @@ SPECTACULAR_PLATFORM_SETTINGS = { # noinspection Mypy SPECTACULAR_B2B_SETTINGS = { - "TITLE": f"{CONSTANCE_CONFIG.get('PROJECT_NAME')[0]} API", + "TITLE": f"{CONSTANCE_CONFIG.get('PROJECT_NAME')[0]} API", # type: ignore [index] "DESCRIPTION": SPECTACULAR_B2B_DESCRIPTION, "VERSION": EVIBES_VERSION, # noqa: F405 "TOS": "https://wiseless.xyz/evibes/terms-of-service", @@ -188,17 +199,17 @@ SPECTACULAR_B2B_SETTINGS = { }, "SERVERS": [ { - "url": f"https://b2b.{CONSTANCE_CONFIG.get('BASE_DOMAIN')[0]}/", + "url": f"https://b2b.{CONSTANCE_CONFIG.get('BASE_DOMAIN')[0]}/", # type: ignore [index] "description": "Production Server", }, { - "url": f"https://beta.b2b.{CONSTANCE_CONFIG.get('BASE_DOMAIN')[0]}/", + "url": f"https://beta.b2b.{CONSTANCE_CONFIG.get('BASE_DOMAIN')[0]}/", # type: ignore [index] "description": "Beta Solutions Server", }, ], "CONTACT": { - "name": f"{CONSTANCE_CONFIG.get('COMPANY_NAME')[0]}", - "email": f"{CONSTANCE_CONFIG.get('EMAIL_HOST_USER')[0]}", - "URL": f"https://www.{CONSTANCE_CONFIG.get('BASE_DOMAIN')[0]}/help", + "name": f"{CONSTANCE_CONFIG.get('COMPANY_NAME')[0]}", # type: ignore [index] + "email": f"{CONSTANCE_CONFIG.get('EMAIL_HOST_USER')[0]}", # type: ignore [index] + "URL": f"https://www.{CONSTANCE_CONFIG.get('BASE_DOMAIN')[0]}/help", # type: ignore [index] }, } diff --git a/evibes/settings/elasticsearch.py b/evibes/settings/elasticsearch.py index 171208e3..257262a3 100644 --- a/evibes/settings/elasticsearch.py +++ b/evibes/settings/elasticsearch.py @@ -1,9 +1,11 @@ -from evibes.settings.base import * # noqa: F403 +from os import getenv + +from evibes.settings import DEBUG ELASTICSEARCH_DSL = { "default": { "hosts": ["http://elasticsearch:9200"], - "http_auth": ("elastic", getenv("ELASTIC_PASSWORD")), # noqa: F405 + "http_auth": ("elastic", getenv("ELASTIC_PASSWORD")), "verify_certs": False, "timeout": 30, "ssl_show_warn": False, @@ -12,6 +14,6 @@ ELASTICSEARCH_DSL = { }, } -ELASTICSEARCH_DSL_AUTOSYNC = DEBUG # noqa: F405 +ELASTICSEARCH_DSL_AUTOSYNC = DEBUG ELASTICSEARCH_DSL_PARALLEL = True ELASTICSEARCH_DSL_SIGNAL_PROCESSOR = "django_elasticsearch_dsl.signals.CelerySignalProcessor" diff --git a/evibes/settings/emailing.py b/evibes/settings/emailing.py index c2eccc79..82dbcd65 100644 --- a/evibes/settings/emailing.py +++ b/evibes/settings/emailing.py @@ -1,9 +1,9 @@ from evibes.settings import CONSTANCE_CONFIG EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" -EMAIL_HOST = CONSTANCE_CONFIG.get("EMAIL_HOST")[0] # type: ignore -EMAIL_PORT = CONSTANCE_CONFIG.get("EMAIL_PORT")[0] # type: ignore -EMAIL_USE_TLS = CONSTANCE_CONFIG.get("EMAIL_USE_TLS")[0] # type: ignore -EMAIL_USE_SSL = CONSTANCE_CONFIG.get("EMAIL_USE_SSL")[0] # type: ignore -EMAIL_HOST_USER = CONSTANCE_CONFIG.get("EMAIL_HOST_USER")[0] # type: ignore -EMAIL_HOST_PASSWORD = CONSTANCE_CONFIG.get("EMAIL_HOST_PASSWORD")[0] # type: ignore +EMAIL_HOST = CONSTANCE_CONFIG.get("EMAIL_HOST")[0] # type: ignore [index] +EMAIL_PORT = CONSTANCE_CONFIG.get("EMAIL_PORT")[0] # type: ignore [index] +EMAIL_USE_TLS = CONSTANCE_CONFIG.get("EMAIL_USE_TLS")[0] # type: ignore [index] +EMAIL_USE_SSL = CONSTANCE_CONFIG.get("EMAIL_USE_SSL")[0] # type: ignore [index] +EMAIL_HOST_USER = CONSTANCE_CONFIG.get("EMAIL_HOST_USER")[0] # type: ignore [index] +EMAIL_HOST_PASSWORD = CONSTANCE_CONFIG.get("EMAIL_HOST_PASSWORD")[0] # type: ignore [index] diff --git a/evibes/settings/extensions.py b/evibes/settings/extensions.py index 44adc7b2..eed9c571 100644 --- a/evibes/settings/extensions.py +++ b/evibes/settings/extensions.py @@ -1,6 +1,12 @@ +# noinspection PyUnresolvedReferences +from evibes.settings.base import * # noqa: F403 + GRAPH_MODELS = { "all_applications": True, "group_models": True, } EXTENSIONS_MAX_UNIQUE_QUERY_ATTEMPTS = 500 + +HEALTHCHECK_CELERY_RESULT_TIMEOUT = 5 +HEALTHCHECK_CELERY_QUEUE_TIMEOUT = 5 diff --git a/evibes/settings/graphene.py b/evibes/settings/graphene.py index 376a410c..e46bd3e7 100644 --- a/evibes/settings/graphene.py +++ b/evibes/settings/graphene.py @@ -1,11 +1,11 @@ -from evibes.settings.base import * # noqa: F403 +from evibes.settings.base import DEBUG GRAPHENE = { "MIDDLEWARE": [ "evibes.middleware.GrapheneLoggingErrorsDebugMiddleware", "evibes.middleware.GrapheneJWTAuthorizationMiddleware", ] - if DEBUG # noqa: F405 + if DEBUG else [ "evibes.middleware.GrapheneJWTAuthorizationMiddleware", ], diff --git a/evibes/settings/jazzmin.py b/evibes/settings/jazzmin.py new file mode 100644 index 00000000..a15ceb1e --- /dev/null +++ b/evibes/settings/jazzmin.py @@ -0,0 +1,63 @@ +from django.utils.translation import gettext_lazy as _ + +from evibes.settings.base import EVIBES_VERSION +from evibes.settings.constance import CONSTANCE_CONFIG + +JAZZMIN_SETTINGS = { + "site_title": f"{CONSTANCE_CONFIG.get('PROJECT_NAME')[0]} Admin", # type: ignore [index] + "site_header": str(CONSTANCE_CONFIG.get("PROJECT_NAME")[0]), # type: ignore [index] + "site_brand": str(CONSTANCE_CONFIG.get("PROJECT_NAME")[0]), # type: ignore [index] + "site_logo": "logo.png", + "login_logo": "logo.png", + "login_logo_dark": "logo.png", + "site_logo_classes": "", + "site_icon": "favicon.ico", + "welcome_sign": "Whoa! Only admins allowed here!", + "copyright": f"eVibes {EVIBES_VERSION} by Wiseless", + "search_model": None, + "user_avatar": "avatar", + "topmenu_links": [ + {"name": _("Home"), "url": "admin:index"}, + {"name": _("Storefront"), "url": f"https://{CONSTANCE_CONFIG.get('BASE_DOMAIN')[0]}", "new_window": True}, # type: ignore [index] + {"name": "GitLab", "url": "https://gitlab.com/wiseless/evibes", "new_window": True}, + { + "name": _("GraphQL Docs"), + "url": f"https://api.{CONSTANCE_CONFIG.get('BASE_DOMAIN')[0]}/graphql", # type: ignore [index] + "new_window": True, + }, + { + "name": _("Platform REST Docs"), + "url": f"https://api.{CONSTANCE_CONFIG.get('BASE_DOMAIN')[0]}/docs/swagger", # type: ignore [index] + "new_window": True, + }, + { + "name": _("B2B REST Docs"), + "url": f"https://b2b.{CONSTANCE_CONFIG.get('BASE_DOMAIN')[0]}/docs/swagger", # type: ignore [index] + "new_window": True, + }, + {"name": _("Support"), "url": "https://t.me/fureunoir", "new_window": True}, + ], + "usermenu_links": [], + "show_sidebar": True, + "navigation_expanded": True, + "hide_apps": ["django_celery_results", ""], + "hide_models": [], + "order_with_respect_to": ["vibes_auth", "core", "payments", "blog"], + "icons": { + "auth": "fas fa-users-cog", + "auth.user": "fas fa-user", + "auth.Group": "fas fa-users", + }, + "default_icon_parents": "fas fa-chevron-circle-right", + "default_icon_children": "fas fa-circle", + "related_modal_active": False, + "use_google_fonts_cdn": True, + "show_ui_builder": True, + "changeform_format": "horizontal_tabs", + "language_chooser": True, +} + +JAZZMIN_UI_TWEAKS = { + "theme": "cyborg", + "dark_mode_theme": "cyborg", +} diff --git a/evibes/settings/logconfig.py b/evibes/settings/logconfig.py index 2168802b..7505042f 100644 --- a/evibes/settings/logconfig.py +++ b/evibes/settings/logconfig.py @@ -1,4 +1,22 @@ -from evibes.settings.base import * # noqa: F403 +import logging + +from evibes.settings.base import DEBUG + + +class SkipVariableDoesNotExistFilter(logging.Filter): + def filter(self, record: logging.LogRecord) -> bool: + if record.exc_info: + exc_type, exc_instance, _ = record.exc_info + try: + if exc_type is not None: + if exc_type.__name__ == "VariableDoesNotExist": + return False + else: + return True + except AttributeError: + return True + return "VariableDoesNotExist" not in record.getMessage() + LOGGING = { "version": 1, @@ -22,67 +40,96 @@ LOGGING = { }, }, "filters": { + "require_debug_false": { + "()": "django.utils.log.RequireDebugFalse", + }, "require_debug_true": { "()": "django.utils.log.RequireDebugTrue", }, + "skip_variable_doesnotexist": { + "()": "evibes.settings.logconfig.SkipVariableDoesNotExistFilter", + }, }, "handlers": { - "console_debug": { - "level": "DEBUG", - "filters": ["require_debug_true"], - "class": "logging.StreamHandler", - "formatter": "color", - }, - "console_production": { - "level": "WARNING", + "console": { "class": "logging.StreamHandler", "formatter": "color", }, "mail_admins": { "level": "ERROR", + "filters": ["require_debug_false"], "class": "django.utils.log.AdminEmailHandler", - "include_html": True, - "formatter": "plain", }, }, "loggers": { "django": { - "handlers": ["console_debug", "console_production"], - "level": "DEBUG" if DEBUG else "INFO", # noqa: F405 + "handlers": [ + "console", + "mail_admins", + ], + "level": "DEBUG" if DEBUG else "INFO", "propagate": True, }, - "django.request": { - "handlers": ["console_debug", "mail_admins"], - "level": "DEBUG" if DEBUG else "INFO", # noqa: F405 + "django.server": { + "level": "INFO", "propagate": False, }, "django.db.backends": { - "handlers": ["console_debug" if DEBUG else "console_production"], # noqa: F405 + "handlers": [ + "console", + "mail_admins", + ], "level": "WARNING", "propagate": False, }, - "core": { - "handlers": ["console_debug" if DEBUG else "console_production"], # noqa: F405 - "level": "DEBUG" if DEBUG else "WARNING", # noqa: F405 + "django.template": { + "handlers": [ + "console", + "mail_admins", + ], + "level": "DEBUG" if DEBUG else "ERROR", "propagate": True, + "filters": ["skip_variable_doesnotexist"], + }, + "gunicorn.access": { + "handlers": [ + "console", + ], + "level": "DEBUG" if DEBUG else "INFO", + "propagate": False, + }, + "gunicorn.error": { + "handlers": [ + "console", + ], + "level": "WARNING", + "propagate": False, }, "django_elasticsearch_dsl": { - "handlers": ["console_debug" if DEBUG else "console_production"], # noqa: F405 + "handlers": [ + "console", + ], "level": "WARNING", "propagate": False, }, "celery.app.trace": { - "handlers": ["console_debug" if DEBUG else "console_production"], # noqa: F405 - "level": "DEBUG" if DEBUG else "INFO", # noqa: F405 + "handlers": [ + "console", + ], + "level": "DEBUG" if DEBUG else "INFO", "propagate": False, }, "celery.worker.strategy": { - "handlers": ["console_debug" if DEBUG else "console_production"], # noqa: F405 - "level": "DEBUG" if DEBUG else "INFO", # noqa: F405 + "handlers": [ + "console", + ], + "level": "DEBUG" if DEBUG else "INFO", "propagate": False, }, "elastic_transport.transport": { - "handlers": ["console_debug" if DEBUG else "console_production"], # noqa: F405 + "handlers": [ + "console", + ], "level": "ERROR", "propagate": False, }, diff --git a/evibes/utils/__init__.py b/evibes/utils/__init__.py index 603e85df..d72283bc 100644 --- a/evibes/utils/__init__.py +++ b/evibes/utils/__init__.py @@ -34,5 +34,5 @@ def evibes_summernote_upload_to_func(instance, filename: str) -> str: filename = f"{uuid.uuid4()}.{ext}" today = datetime.now().strftime("%Y-%m-%d") if instance: - return os.path.join('evibes-summernote', today, filename) - return os.path.join('evibes-summernote', today) + return os.path.join("evibes-summernote", today, filename) + return os.path.join("evibes-summernote", today) diff --git a/payments/admin.py b/payments/admin.py index 9de87f4b..d53f51b8 100644 --- a/payments/admin.py +++ b/payments/admin.py @@ -1,8 +1,8 @@ -# noinspection PyUnresolvedReferences from django.contrib import admin +from django.contrib.admin import ModelAdmin, register from django.utils.translation import gettext_lazy as _ -from core.admin import BasicModelAdmin +from core.admin import ActivationActionsMixin from payments.forms import TransactionForm from payments.models import Balance, Transaction @@ -20,7 +20,8 @@ class TransactionInline(admin.TabularInline): return qs.select_related("order") -class BalanceAdmin(BasicModelAdmin): +@register(Balance) +class BalanceAdmin(ActivationActionsMixin, ModelAdmin): # type: ignore [misc] inlines = (TransactionInline,) list_display = ("user", "amount") search_fields = ("user__email",) @@ -31,13 +32,10 @@ class BalanceAdmin(BasicModelAdmin): return qs.prefetch_related("transactions", "user") -class TransactionAdmin(BasicModelAdmin): - list_display = ("balance", "amount", "currency", "payment_method", "order") +@register(Transaction) +class TransactionAdmin(ActivationActionsMixin, ModelAdmin): # type: ignore [misc] + list_display = ("balance", "amount", "order", "modified", "created") search_fields = ("balance__user__email", "currency", "payment_method") list_filter = ("currency", "payment_method") ordering = ("balance",) form = TransactionForm - - -admin.site.register(Balance, BalanceAdmin) -admin.site.register(Transaction, TransactionAdmin) diff --git a/payments/graphene/object_types.py b/payments/graphene/object_types.py index 69d59408..c39091a3 100644 --- a/payments/graphene/object_types.py +++ b/payments/graphene/object_types.py @@ -11,8 +11,9 @@ class TransactionType(DjangoObjectType): process = GenericScalar() def resolve_process(self: Transaction, info) -> dict: - if info.context.user == self.balance.user: - return self.process + if self.balance is not None: + if info.context.user == self.balance.user: + return self.process return {} class Meta: diff --git a/payments/locale/ar_AR/LC_MESSAGES/django.mo b/payments/locale/ar_AR/LC_MESSAGES/django.mo index f4ff31c0..fc2d8807 100644 Binary files a/payments/locale/ar_AR/LC_MESSAGES/django.mo and b/payments/locale/ar_AR/LC_MESSAGES/django.mo differ diff --git a/payments/locale/ar_AR/LC_MESSAGES/django.po b/payments/locale/ar_AR/LC_MESSAGES/django.po index 5a8dfcc9..736fd372 100644 --- a/payments/locale/ar_AR/LC_MESSAGES/django.po +++ b/payments/locale/ar_AR/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "المعاملات" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "المعاملات" @@ -41,15 +41,15 @@ msgstr "الإيداع في الرصيد" msgid "deposit some money to balance" msgstr "إيداع بعض الأموال لتحقيق التوازن" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "طلب المعالجة بعد الدفع" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "تفاصيل المعالجة" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -58,29 +58,29 @@ msgstr "" "يجب أن يتناسب مبلغ المعاملة مع " "{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}" -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "الرصيد" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "الموازين" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "إيداع الرصيد" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "الشعار" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "مرحباً %(user_first_name)s," -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -89,7 +89,7 @@ msgstr "" "لقد نجحنا في إيداع رصيد حسابك في %(amount)s. رصيدك الحالي\n" " رصيدك الحالي هو %(balance)s__." -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -98,12 +98,12 @@ msgstr "" "إذا كان لديك أي أسئلة، فلا تتردد في الاتصال بدعمنا على\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "مع أطيب تحياتي،
فريق%(project_name)s" +msgstr "مع أطيب تحياتي،
فريق %(project_name)s" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "جميع الحقوق محفوظة" @@ -114,9 +114,9 @@ msgstr "مطلوب مزود للحصول على الأسعار من" #: payments/utils/__init__.py:15 #, python-brace-format msgid "couldn't find provider {provider}" -msgstr "تعذّر العثور على الموفر {provider}" +msgstr "تعذر العثور على مزود {provider}" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME} | إيداع الرصيد" diff --git a/payments/locale/cs_CZ/LC_MESSAGES/django.mo b/payments/locale/cs_CZ/LC_MESSAGES/django.mo index 56456447..32cd1d95 100644 Binary files a/payments/locale/cs_CZ/LC_MESSAGES/django.mo and b/payments/locale/cs_CZ/LC_MESSAGES/django.mo differ diff --git a/payments/locale/cs_CZ/LC_MESSAGES/django.po b/payments/locale/cs_CZ/LC_MESSAGES/django.po index e7ed0f46..7cb81ebe 100644 --- a/payments/locale/cs_CZ/LC_MESSAGES/django.po +++ b/payments/locale/cs_CZ/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "Transakce" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "Transakce" @@ -41,15 +41,15 @@ msgstr "Vklad do zůstatku" msgid "deposit some money to balance" msgstr "Vložte nějaké peníze na účet" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "Objednávka ke zpracování po zaplacení" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "Podrobnosti o zpracování" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -58,29 +58,29 @@ msgstr "" "Částka transakce se musí vejít do rozmezí " "{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}." -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "Bilance" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "Váhy" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "Zůstatková záloha" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "Logo" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "Ahoj %(user_first_name)s," -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -89,7 +89,7 @@ msgstr "" "Na váš účet jsme úspěšně připsali %(amount)s. Váš aktuální\n" " je %(balance)s." -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -98,12 +98,12 @@ msgstr "" "Pokud máte jakékoli dotazy, neváhejte kontaktovat naši podporu na adrese\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "S pozdravem,
tým %(project_name)s" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "Všechna práva vyhrazena" @@ -116,7 +116,7 @@ msgstr "Je třeba mít poskytovatele, od kterého lze získat sazby" msgid "couldn't find provider {provider}" msgstr "Nepodařilo se najít poskytovatele {provider}" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME} | Zůstatek vkladu" diff --git a/payments/locale/da_DK/LC_MESSAGES/django.mo b/payments/locale/da_DK/LC_MESSAGES/django.mo index a6f7f29b..e7504b30 100644 Binary files a/payments/locale/da_DK/LC_MESSAGES/django.mo and b/payments/locale/da_DK/LC_MESSAGES/django.mo differ diff --git a/payments/locale/da_DK/LC_MESSAGES/django.po b/payments/locale/da_DK/LC_MESSAGES/django.po index b57ddfa8..0bb3bc3c 100644 --- a/payments/locale/da_DK/LC_MESSAGES/django.po +++ b/payments/locale/da_DK/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "Transaktion" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "Transaktioner" @@ -41,15 +41,15 @@ msgstr "Indbetaling til saldo" msgid "deposit some money to balance" msgstr "Sæt nogle penge ind på saldoen" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "Ordre til behandling efter betaling" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "Behandling af detaljer" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -58,29 +58,29 @@ msgstr "" "Transaktionsbeløbet skal passe ind i " "{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}." -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "Balance" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "Vægte" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "Saldoindbetaling" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "Logo" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "Hej %(user_first_name)s," -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -89,7 +89,7 @@ msgstr "" "Vi har krediteret din konto med %(amount)s. Din nuværende\n" " saldo er %(balance)s." -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -98,12 +98,12 @@ msgstr "" "Hvis du har spørgsmål, er du velkommen til at kontakte vores support på\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Med venlig hilsen,
teamet %(project_name)s." -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "Alle rettigheder forbeholdes" @@ -114,9 +114,9 @@ msgstr "Der er brug for en udbyder at få priser fra" #: payments/utils/__init__.py:15 #, python-brace-format msgid "couldn't find provider {provider}" -msgstr "Kunne ikke finde udbyder {provider}" +msgstr "Kunne ikke finde udbyder {provider}." -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME} | Saldoindbetaling" diff --git a/payments/locale/de_DE/LC_MESSAGES/django.mo b/payments/locale/de_DE/LC_MESSAGES/django.mo index 60228123..b2262d8f 100644 Binary files a/payments/locale/de_DE/LC_MESSAGES/django.mo and b/payments/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/payments/locale/de_DE/LC_MESSAGES/django.po b/payments/locale/de_DE/LC_MESSAGES/django.po index 15de2683..a8c78ad8 100644 --- a/payments/locale/de_DE/LC_MESSAGES/django.po +++ b/payments/locale/de_DE/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "Transaktion" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "Transaktionen" @@ -41,15 +41,15 @@ msgstr "Einzahlung auf den Saldo" msgid "deposit some money to balance" msgstr "Einzahlung von Geld zum Ausgleich" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "Auftrag zur Bearbeitung nach Bezahlung" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "Details zur Verarbeitung" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -58,29 +58,29 @@ msgstr "" "Der Transaktionsbetrag muss zwischen " "{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM} liegen" -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "Waage" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "Waagen" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "Balance Deposit" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "Logo" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "Hallo %(user_first_name)s," -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -89,7 +89,7 @@ msgstr "" "Wir haben Ihrem Konto erfolgreich %(amount)s gutgeschrieben. Ihr aktuelles\n" " Saldo beträgt %(balance)s." -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -98,12 +98,12 @@ msgstr "" "Wenn Sie Fragen haben, wenden Sie sich bitte an unseren Support unter\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Mit freundlichen Grüßen,
das %(project_name)s-Team" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "Alle Rechte vorbehalten" @@ -116,7 +116,7 @@ msgstr "Sie benötigen einen Anbieter, bei dem Sie die Preise erfragen können." msgid "couldn't find provider {provider}" msgstr "Anbieter {provider} konnte nicht gefunden werden" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME} | Saldo Einzahlung" diff --git a/payments/locale/en_GB/LC_MESSAGES/django.mo b/payments/locale/en_GB/LC_MESSAGES/django.mo index 00eb93a4..c40f51f0 100644 Binary files a/payments/locale/en_GB/LC_MESSAGES/django.mo and b/payments/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/payments/locale/en_GB/LC_MESSAGES/django.po b/payments/locale/en_GB/LC_MESSAGES/django.po index c6bb4455..2268b1e3 100644 --- a/payments/locale/en_GB/LC_MESSAGES/django.po +++ b/payments/locale/en_GB/LC_MESSAGES/django.po @@ -5,9 +5,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -17,11 +17,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "Transaction" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "Transactions" @@ -45,46 +45,46 @@ msgstr "Deposit to balance" msgid "deposit some money to balance" msgstr "Deposit some money to balance" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "Order to process after paid" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "Processing details" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" -"transaction amount must fit into {config.PAYMENT_GATEWAY_MINIMUM}-{config." -"PAYMENT_GATEWAY_MAXIMUM}" +"transaction amount must fit into " +"{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}" msgstr "" -"Transaction amount must fit into {config.PAYMENT_GATEWAY_MINIMUM}-{config." -"PAYMENT_GATEWAY_MAXIMUM}" +"Transaction amount must fit into " +"{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}" -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "Balance" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "Balances" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "Balance Deposit" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "Logo" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "Hello %(user_first_name)s," -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -93,7 +93,7 @@ msgstr "" "We have successfully credited your account with %(amount)s. Your current\n" " balance is %(balance)s." -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -102,12 +102,12 @@ msgstr "" "If you have any questions, feel free to contact our support at\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Best regards,
the %(project_name)s team" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "All rights reserved" @@ -120,7 +120,7 @@ msgstr "A provider to get rates from is required" msgid "couldn't find provider {provider}" msgstr "Couldn't find provider {provider}" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME} | Balance Deposit" diff --git a/payments/locale/en_US/LC_MESSAGES/django.mo b/payments/locale/en_US/LC_MESSAGES/django.mo index b5d49a6e..caeca9cb 100644 Binary files a/payments/locale/en_US/LC_MESSAGES/django.mo and b/payments/locale/en_US/LC_MESSAGES/django.mo differ diff --git a/payments/locale/en_US/LC_MESSAGES/django.po b/payments/locale/en_US/LC_MESSAGES/django.po index f6465785..4afec807 100644 --- a/payments/locale/en_US/LC_MESSAGES/django.po +++ b/payments/locale/en_US/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "Transaction" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "Transactions" @@ -41,15 +41,15 @@ msgstr "Deposit to balance" msgid "deposit some money to balance" msgstr "Deposit some money to balance" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "Order to process after paid" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "Processing details" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -58,29 +58,29 @@ msgstr "" "Transaction amount must fit into " "{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}" -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "Balance" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "Scales" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "Balance Deposit" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "Logo" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "Hello %(user_first_name)s," -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -89,7 +89,7 @@ msgstr "" "We have successfully credited your account with %(amount)s. Your current\n" " balance is %(balance)s." -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -98,12 +98,12 @@ msgstr "" "If you have any questions, feel free to contact our support at\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Best regards,
the %(project_name)s team" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "All rights reserved" @@ -116,7 +116,7 @@ msgstr "A provider to get rates from is required" msgid "couldn't find provider {provider}" msgstr "Couldn't find provider {provider}" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME} | Balance Deposit" diff --git a/payments/locale/es_ES/LC_MESSAGES/django.mo b/payments/locale/es_ES/LC_MESSAGES/django.mo index 7829282b..8d3f7a8a 100644 Binary files a/payments/locale/es_ES/LC_MESSAGES/django.mo and b/payments/locale/es_ES/LC_MESSAGES/django.mo differ diff --git a/payments/locale/es_ES/LC_MESSAGES/django.po b/payments/locale/es_ES/LC_MESSAGES/django.po index 1de2abb2..22e9be2d 100644 --- a/payments/locale/es_ES/LC_MESSAGES/django.po +++ b/payments/locale/es_ES/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "Transacción" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "Transacciones" @@ -41,15 +41,15 @@ msgstr "Depósito a cuenta" msgid "deposit some money to balance" msgstr "Depositar dinero para equilibrar" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "Orden a tramitar una vez pagada" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "Detalles del proceso" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -58,29 +58,29 @@ msgstr "" "El importe de la transacción debe ajustarse a " "{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}" -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "Saldo" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "Escalas" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "Depósito de saldo" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "Logotipo" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "Hola %(user_first_name)s," -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -89,7 +89,7 @@ msgstr "" "Hemos ingresado correctamente %(amount)s en su cuenta. Su saldo\n" " actual es de %(balance)s." -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -98,12 +98,12 @@ msgstr "" "Si tiene alguna pregunta, no dude en ponerse en contacto con nuestro servicio de asistencia en\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Saludos cordiales,
el equipo %(project_name)s" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "Todos los derechos reservados" @@ -114,9 +114,9 @@ msgstr "Se necesita un proveedor del que obtener tarifas" #: payments/utils/__init__.py:15 #, python-brace-format msgid "couldn't find provider {provider}" -msgstr "No se ha podido encontrar el proveedor {provider}" +msgstr "No se pudo encontrar el proveedor {provider}" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME} | Depósito de saldo" diff --git a/payments/locale/fr_FR/LC_MESSAGES/django.mo b/payments/locale/fr_FR/LC_MESSAGES/django.mo index d8d54560..b154dd0c 100644 Binary files a/payments/locale/fr_FR/LC_MESSAGES/django.mo and b/payments/locale/fr_FR/LC_MESSAGES/django.mo differ diff --git a/payments/locale/fr_FR/LC_MESSAGES/django.po b/payments/locale/fr_FR/LC_MESSAGES/django.po index 2319678c..faafb50b 100644 --- a/payments/locale/fr_FR/LC_MESSAGES/django.po +++ b/payments/locale/fr_FR/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "Transaction" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "Transactions" @@ -41,15 +41,15 @@ msgstr "Dépôt au solde" msgid "deposit some money to balance" msgstr "Déposer de l'argent sur le compte" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "Commande à traiter après paiement" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "Détails du traitement" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -58,29 +58,29 @@ msgstr "" "Le montant de la transaction doit être compris entre " "{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}." -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "Balance" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "Balances" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "Balance Deposit" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "Logo" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "Bonjour %(user_first_name)s," -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -89,7 +89,7 @@ msgstr "" "Nous avons crédité votre compte de %(amount)s. Votre solde\n" " est de %(balance)s." -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -98,12 +98,12 @@ msgstr "" "Si vous avez des questions, n'hésitez pas à contacter notre service d'assistance à l'adresse suivante\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Meilleures salutations,
l'équipe %(project_name)s" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "Tous droits réservés" @@ -117,7 +117,7 @@ msgstr "" msgid "couldn't find provider {provider}" msgstr "Impossible de trouver le fournisseur {provider}" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME} | Dépôt de solde" diff --git a/payments/locale/hi_IN/LC_MESSAGES/django.mo b/payments/locale/hi_IN/LC_MESSAGES/django.mo index 0fc354f2..47c1f925 100644 Binary files a/payments/locale/hi_IN/LC_MESSAGES/django.mo and b/payments/locale/hi_IN/LC_MESSAGES/django.mo differ diff --git a/payments/locale/hi_IN/LC_MESSAGES/django.po b/payments/locale/hi_IN/LC_MESSAGES/django.po index c93e735e..879b9332 100644 --- a/payments/locale/hi_IN/LC_MESSAGES/django.po +++ b/payments/locale/hi_IN/LC_MESSAGES/django.po @@ -2,12 +2,12 @@ # Copyright (C) 2025 EGOR GORBUNOV # This file is distributed under the same license as the EVIBES package. # EGOR GORBUNOV , 2025. -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:40+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -16,11 +16,11 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "" @@ -44,63 +44,63 @@ msgstr "" msgid "deposit some money to balance" msgstr "" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into {config.PAYMENT_GATEWAY_MINIMUM}-{config." "PAYMENT_GATEWAY_MAXIMUM}" msgstr "" -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "" -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" " balance is %(balance)s." msgstr "" -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" " %(contact_email)s." msgstr "" -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "" @@ -113,7 +113,7 @@ msgstr "" msgid "couldn't find provider {provider}" msgstr "" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "" diff --git a/payments/locale/it_IT/LC_MESSAGES/django.mo b/payments/locale/it_IT/LC_MESSAGES/django.mo index 021e8f7b..06bc4086 100644 Binary files a/payments/locale/it_IT/LC_MESSAGES/django.mo and b/payments/locale/it_IT/LC_MESSAGES/django.mo differ diff --git a/payments/locale/it_IT/LC_MESSAGES/django.po b/payments/locale/it_IT/LC_MESSAGES/django.po index 50d12ae9..f3998be7 100644 --- a/payments/locale/it_IT/LC_MESSAGES/django.po +++ b/payments/locale/it_IT/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "Transazione" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "Transazioni" @@ -41,15 +41,15 @@ msgstr "Deposito a saldo" msgid "deposit some money to balance" msgstr "Depositare del denaro per bilanciare" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "Ordine da elaborare dopo il pagamento" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "Dettagli di elaborazione" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -58,29 +58,29 @@ msgstr "" "L'importo della transazione deve rientrare in " "{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}" -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "Equilibrio" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "Bilance" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "Saldo Deposito" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "Logo" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "Hello %(user_first_name)s," -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -89,7 +89,7 @@ msgstr "" "Abbiamo accreditato il vostro conto con %(amount)s. Il suo saldo attuale\n" " saldo è %(balance)s." -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -98,12 +98,12 @@ msgstr "" "In caso di domande, non esitate a contattare il nostro supporto all'indirizzo\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Cordiali saluti,
il team %(project_name)s" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "Tutti i diritti riservati" @@ -116,7 +116,7 @@ msgstr "È necessario un fornitore da cui ottenere le tariffe" msgid "couldn't find provider {provider}" msgstr "Impossibile trovare il fornitore {provider}" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME} | Deposito a saldo" diff --git a/payments/locale/ja_JP/LC_MESSAGES/django.mo b/payments/locale/ja_JP/LC_MESSAGES/django.mo index e37cf94c..595b2e3e 100644 Binary files a/payments/locale/ja_JP/LC_MESSAGES/django.mo and b/payments/locale/ja_JP/LC_MESSAGES/django.mo differ diff --git a/payments/locale/ja_JP/LC_MESSAGES/django.po b/payments/locale/ja_JP/LC_MESSAGES/django.po index 4c8d5b7d..8eecbd21 100644 --- a/payments/locale/ja_JP/LC_MESSAGES/django.po +++ b/payments/locale/ja_JP/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "トランザクション" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "トランザクション" @@ -41,15 +41,15 @@ msgstr "預金残高" msgid "deposit some money to balance" msgstr "預金残高を増やす" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "支払い後の処理順序" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "加工内容" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -57,29 +57,29 @@ msgid "" msgstr "" "取引金額は{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}に収まる必要があります。" -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "バランス" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "体重計" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "預金残高" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "ロゴ" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "こんにちは%(user_first_name)s、" -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -88,7 +88,7 @@ msgstr "" "お客様の口座に%(amount)sが入金されました。あなたの現在の\n" " 現在の残高は%(balance)sです。" -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -97,12 +97,12 @@ msgstr "" "ご不明な点がございましたら、お気軽に下記までお問い合わせください。\n" " %(contact_email)s。" -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "よろしくお願いします、
%(project_name)sチーム" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "無断複写・転載を禁じます。" @@ -113,9 +113,9 @@ msgstr "レートを取得するプロバイダーが必要" #: payments/utils/__init__.py:15 #, python-brace-format msgid "couldn't find provider {provider}" -msgstr "{provider}プロバイダーが見つかりません。" +msgstr "プロバイダーが見つかりませんでした {provider} 。" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME}| 預金残高" diff --git a/payments/locale/kk_KZ/LC_MESSAGES/django.mo b/payments/locale/kk_KZ/LC_MESSAGES/django.mo index 0fc354f2..47c1f925 100644 Binary files a/payments/locale/kk_KZ/LC_MESSAGES/django.mo and b/payments/locale/kk_KZ/LC_MESSAGES/django.mo differ diff --git a/payments/locale/kk_KZ/LC_MESSAGES/django.po b/payments/locale/kk_KZ/LC_MESSAGES/django.po index c93e735e..879b9332 100644 --- a/payments/locale/kk_KZ/LC_MESSAGES/django.po +++ b/payments/locale/kk_KZ/LC_MESSAGES/django.po @@ -2,12 +2,12 @@ # Copyright (C) 2025 EGOR GORBUNOV # This file is distributed under the same license as the EVIBES package. # EGOR GORBUNOV , 2025. -# +# msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:40+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -16,11 +16,11 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "" @@ -44,63 +44,63 @@ msgstr "" msgid "deposit some money to balance" msgstr "" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into {config.PAYMENT_GATEWAY_MINIMUM}-{config." "PAYMENT_GATEWAY_MAXIMUM}" msgstr "" -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "" -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" " balance is %(balance)s." msgstr "" -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" " %(contact_email)s." msgstr "" -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "" @@ -113,7 +113,7 @@ msgstr "" msgid "couldn't find provider {provider}" msgstr "" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "" diff --git a/payments/locale/nl_NL/LC_MESSAGES/django.mo b/payments/locale/nl_NL/LC_MESSAGES/django.mo index 660b9a17..9788cbe8 100644 Binary files a/payments/locale/nl_NL/LC_MESSAGES/django.mo and b/payments/locale/nl_NL/LC_MESSAGES/django.mo differ diff --git a/payments/locale/nl_NL/LC_MESSAGES/django.po b/payments/locale/nl_NL/LC_MESSAGES/django.po index 76999271..b047c098 100644 --- a/payments/locale/nl_NL/LC_MESSAGES/django.po +++ b/payments/locale/nl_NL/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "Transactie" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "Transacties" @@ -41,15 +41,15 @@ msgstr "Storting op saldo" msgid "deposit some money to balance" msgstr "Stort wat geld om te balanceren" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "Order te verwerken na betaling" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "Verwerkingsdetails" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -58,29 +58,29 @@ msgstr "" "Het transactiebedrag moet passen binnen " "{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}." -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "Saldo" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "Weegschaal" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "Saldo Storting" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "Logo" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "Hallo %(user_first_name)s," -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -89,7 +89,7 @@ msgstr "" "We hebben uw rekening succesvol gecrediteerd met %(amount)s. Uw huidige\n" " saldo is %(balance)s." -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -98,12 +98,12 @@ msgstr "" "Als u vragen hebt, kunt u contact opnemen met onze klantenservice op\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Vriendelijke groeten,
het %(project_name)s team" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "Alle rechten voorbehouden" @@ -114,9 +114,9 @@ msgstr "Een provider om tarieven van te krijgen is vereist" #: payments/utils/__init__.py:15 #, python-brace-format msgid "couldn't find provider {provider}" -msgstr "Kon provider {provider} niet vinden" +msgstr "Kon provider {provider} niet vinden." -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME} | Saldo storting" diff --git a/payments/locale/pl_PL/LC_MESSAGES/django.mo b/payments/locale/pl_PL/LC_MESSAGES/django.mo index 6134527e..0e386c06 100644 Binary files a/payments/locale/pl_PL/LC_MESSAGES/django.mo and b/payments/locale/pl_PL/LC_MESSAGES/django.mo differ diff --git a/payments/locale/pl_PL/LC_MESSAGES/django.po b/payments/locale/pl_PL/LC_MESSAGES/django.po index 3e8005d4..f59fb8fd 100644 --- a/payments/locale/pl_PL/LC_MESSAGES/django.po +++ b/payments/locale/pl_PL/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "Transakcja" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "Transakcje" @@ -41,15 +41,15 @@ msgstr "Wpłata na saldo" msgid "deposit some money to balance" msgstr "Wpłać trochę pieniędzy na saldo" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "Zamówienie do przetworzenia po opłaceniu" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "Szczegóły przetwarzania" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -58,29 +58,29 @@ msgstr "" "Kwota transakcji musi mieścić się w przedziale " "{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}." -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "Równowaga" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "Wagi" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "Saldo depozytu" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "Logo" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "Witaj %(user_first_name)s," -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -89,7 +89,7 @@ msgstr "" "Twoje konto zostało pomyślnie zasilone kwotą %(amount)s. Aktualne\n" " wynosi %(balance)s." -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -98,12 +98,12 @@ msgstr "" "Jeśli masz jakiekolwiek pytania, skontaktuj się z naszym działem pomocy technicznej pod adresem\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Najlepsze pozdrowienia,
zespół %(project_name)s" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "Wszelkie prawa zastrzeżone" @@ -114,9 +114,9 @@ msgstr "Wymagany jest dostawca, od którego można uzyskać stawki" #: payments/utils/__init__.py:15 #, python-brace-format msgid "couldn't find provider {provider}" -msgstr "Nie można znaleźć dostawcy {provider}." +msgstr "Nie można znaleźć dostawcy {provider}" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME} | Wpłata salda" diff --git a/payments/locale/pt_BR/LC_MESSAGES/django.mo b/payments/locale/pt_BR/LC_MESSAGES/django.mo index a4c815ff..6ec393d6 100644 Binary files a/payments/locale/pt_BR/LC_MESSAGES/django.mo and b/payments/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/payments/locale/pt_BR/LC_MESSAGES/django.po b/payments/locale/pt_BR/LC_MESSAGES/django.po index 9ca89ceb..9a078627 100644 --- a/payments/locale/pt_BR/LC_MESSAGES/django.po +++ b/payments/locale/pt_BR/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "Transação" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "Transações" @@ -41,15 +41,15 @@ msgstr "Depósito no saldo" msgid "deposit some money to balance" msgstr "Depositar algum dinheiro no saldo" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "Ordem a ser processada após o pagamento" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "Detalhes do processamento" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -58,29 +58,29 @@ msgstr "" "O valor da transação deve se enquadrar em " "{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}" -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "Equilíbrio" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "Balanças" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "Depósito de saldo" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "Logotipo" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "Olá %(user_first_name)s," -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -89,7 +89,7 @@ msgstr "" "Creditamos sua conta com %(amount)s com sucesso. Seu saldo atual\n" " saldo atual é %(balance)s." -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -98,12 +98,12 @@ msgstr "" "Se tiver alguma dúvida, entre em contato com o nosso suporte em\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Atenciosamente,
a equipe %(project_name)s" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "Todos os direitos reservados" @@ -116,7 +116,7 @@ msgstr "É necessário um provedor para obter as tarifas" msgid "couldn't find provider {provider}" msgstr "Não foi possível encontrar o provedor {provider}" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME} | Depósito de saldo" diff --git a/payments/locale/ro_RO/LC_MESSAGES/django.mo b/payments/locale/ro_RO/LC_MESSAGES/django.mo index c68e1d82..06d0094e 100644 Binary files a/payments/locale/ro_RO/LC_MESSAGES/django.mo and b/payments/locale/ro_RO/LC_MESSAGES/django.mo differ diff --git a/payments/locale/ro_RO/LC_MESSAGES/django.po b/payments/locale/ro_RO/LC_MESSAGES/django.po index 6c4601d8..9a98693c 100644 --- a/payments/locale/ro_RO/LC_MESSAGES/django.po +++ b/payments/locale/ro_RO/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "Tranzacție" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "Tranzacții" @@ -41,15 +41,15 @@ msgstr "Depozit la sold" msgid "deposit some money to balance" msgstr "Depuneți niște bani la sold" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "Ordin de procesare după plată" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "Detalii de prelucrare" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -58,29 +58,29 @@ msgstr "" "Valoarea tranzacției trebuie să se încadreze în " "{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}" -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "Echilibru" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "Balanță" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "Sold Depozit" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "Logo" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "Bună ziua %(user_first_name)s," -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -89,7 +89,7 @@ msgstr "" "Am creditat cu succes contul dvs. cu %(amount)s. Soldul dvs. actual\n" " actual este %(balance)s." -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -98,12 +98,12 @@ msgstr "" "Dacă aveți întrebări, nu ezitați să contactați asistența noastră la\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "Cele mai bune salutări,
echipa %(project_name)s" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "Toate drepturile rezervate" @@ -116,7 +116,7 @@ msgstr "Este necesar un furnizor de la care să se obțină tarife" msgid "couldn't find provider {provider}" msgstr "Nu am putut găsi furnizorul {provider}" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME} | Depozit sold" diff --git a/payments/locale/ru_RU/LC_MESSAGES/django.mo b/payments/locale/ru_RU/LC_MESSAGES/django.mo index 19bd0d56..b22307d9 100644 Binary files a/payments/locale/ru_RU/LC_MESSAGES/django.mo and b/payments/locale/ru_RU/LC_MESSAGES/django.mo differ diff --git a/payments/locale/ru_RU/LC_MESSAGES/django.po b/payments/locale/ru_RU/LC_MESSAGES/django.po index 57dfa416..ce969f65 100644 --- a/payments/locale/ru_RU/LC_MESSAGES/django.po +++ b/payments/locale/ru_RU/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "Транзакция" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "Транзакции" @@ -41,15 +41,15 @@ msgstr "Депозит на баланс" msgid "deposit some money to balance" msgstr "Внесите немного денег на баланс" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "Заказ на обработку после оплаты" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "Детали обработки" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -58,29 +58,29 @@ msgstr "" "Сумма транзакции должна вписываться в " "{config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM}" -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "Баланс" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" -msgstr "Весы" +msgstr "Балансы" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "Балансовый депозит" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "Логотип" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "Привет %(user_first_name)s," -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -89,7 +89,7 @@ msgstr "" "Мы успешно зачислили на ваш счет %(amount)s. Ваш текущий\n" " баланс составляет %(balance)s." -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -98,12 +98,12 @@ msgstr "" "Если у вас возникнут вопросы, обращайтесь в нашу службу поддержки по адресу\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "С наилучшими пожеланиями,
команда %(project_name)s" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "Все права защищены" @@ -116,7 +116,7 @@ msgstr "Требуется поставщик, у которого можно п msgid "couldn't find provider {provider}" msgstr "Не удалось найти провайдера {provider}" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME} | Депозит баланса" diff --git a/payments/locale/zh_Hans/LC_MESSAGES/django.mo b/payments/locale/zh_Hans/LC_MESSAGES/django.mo index fc816df9..46df8adf 100644 Binary files a/payments/locale/zh_Hans/LC_MESSAGES/django.mo and b/payments/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/payments/locale/zh_Hans/LC_MESSAGES/django.po b/payments/locale/zh_Hans/LC_MESSAGES/django.po index 3f639b94..2c9e8f9e 100644 --- a/payments/locale/zh_Hans/LC_MESSAGES/django.po +++ b/payments/locale/zh_Hans/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-22 18:07+0100\n" +"POT-Creation-Date: 2025-07-03 18:33+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -13,11 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: payments/admin.py:15 payments/models.py:43 +#: payments/admin.py:15 payments/models.py:41 msgid "transaction" msgstr "交易" -#: payments/admin.py:16 payments/models.py:44 +#: payments/admin.py:16 payments/models.py:42 msgid "transactions" msgstr "交易" @@ -41,15 +41,15 @@ msgstr "余额存款" msgid "deposit some money to balance" msgstr "为余额存入一些钱" -#: payments/models.py:21 +#: payments/models.py:19 msgid "order to process after paid" msgstr "付款后处理订单" -#: payments/models.py:24 +#: payments/models.py:22 msgid "processing details" msgstr "处理细节" -#: payments/models.py:39 +#: payments/models.py:37 #, python-brace-format msgid "" "transaction amount must fit into " @@ -58,29 +58,29 @@ msgstr "" "交易金额必须符合 {config.PAYMENT_GATEWAY_MINIMUM}-{config.PAYMENT_GATEWAY_MAXIMUM} " "的规定。" -#: payments/models.py:61 +#: payments/models.py:59 msgid "balance" msgstr "平衡" -#: payments/models.py:62 +#: payments/models.py:60 msgid "balances" msgstr "天平" -#: payments/templates/balance_deposit_email.html:7 -#: payments/templates/balance_deposit_email.html:100 +#: payments/templates/balance_deposit_email.html:6 +#: payments/templates/balance_deposit_email.html:93 msgid "balance deposit" msgstr "余额存款" -#: payments/templates/balance_deposit_email.html:95 +#: payments/templates/balance_deposit_email.html:88 msgid "logo" msgstr "标志" -#: payments/templates/balance_deposit_email.html:101 +#: payments/templates/balance_deposit_email.html:94 #, python-format msgid "hello %(user_first_name)s," msgstr "你好%(user_first_name)s_、" -#: payments/templates/balance_deposit_email.html:102 +#: payments/templates/balance_deposit_email.html:95 #, python-format msgid "" "we have successfully credited your account with %(amount)s. your current\n" @@ -89,7 +89,7 @@ msgstr "" "我们已成功地将 %(amount)s_记入您的账户。您目前的\n" " 余额为%(balance)s_。" -#: payments/templates/balance_deposit_email.html:105 +#: payments/templates/balance_deposit_email.html:98 #, python-format msgid "" "if you have any questions, feel free to contact our support at\n" @@ -98,12 +98,12 @@ msgstr "" "如果您有任何问题,请随时通过以下方式联系我们的支持人员\n" " %(contact_email)s." -#: payments/templates/balance_deposit_email.html:107 +#: payments/templates/balance_deposit_email.html:100 #, python-format msgid "best regards,
the %(project_name)s team" msgstr "致以最诚挚的问候,
%(project_name)s_团队" -#: payments/templates/balance_deposit_email.html:113 +#: payments/templates/balance_deposit_email.html:106 msgid "all rights reserved" msgstr "保留所有权利" @@ -114,9 +114,9 @@ msgstr "需要提供商提供费率" #: payments/utils/__init__.py:15 #, python-brace-format msgid "couldn't find provider {provider}" -msgstr "找不到提供方 {provider}" +msgstr "找不到提供商 {provider}" -#: payments/utils/emailing.py:27 +#: payments/utils/emailing.py:31 #, python-brace-format msgid "{config.PROJECT_NAME} | balance deposit" msgstr "{config.PROJECT_NAME}| 余额存款" diff --git a/payments/migrations/0001_initial.py b/payments/migrations/0001_initial.py index 1dd62ba0..06280b64 100644 --- a/payments/migrations/0001_initial.py +++ b/payments/migrations/0001_initial.py @@ -9,55 +9,96 @@ from django.db import migrations, models class Migration(migrations.Migration): initial = True - dependencies = [ - ] + dependencies = [] operations = [ migrations.CreateModel( - name='Balance', + name="Balance", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('amount', models.FloatField(default=0)), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ("amount", models.FloatField(default=0)), ], options={ - 'verbose_name': 'balance', - 'verbose_name_plural': 'balances', + "verbose_name": "balance", + "verbose_name_plural": "balances", }, ), migrations.CreateModel( - name='Transaction', + name="Transaction", fields=[ - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('is_active', models.BooleanField(default=True, - help_text="if set to false, this object can't be seen by users without needed permission", - verbose_name='is active')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('amount', models.FloatField()), - ('currency', models.CharField(max_length=3)), - ('payment_method', models.CharField(max_length=20)), - ('process', models.JSONField(default=dict, verbose_name='processing details')), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ("amount", models.FloatField()), + ("currency", models.CharField(max_length=3)), + ("payment_method", models.CharField(max_length=20)), + ("process", models.JSONField(default=dict, verbose_name="processing details")), ], options={ - 'verbose_name': 'transaction', - 'verbose_name_plural': 'transactions', + "verbose_name": "transaction", + "verbose_name_plural": "transactions", }, ), ] diff --git a/payments/migrations/0002_initial.py b/payments/migrations/0002_initial.py index d9618a27..480ec9b6 100644 --- a/payments/migrations/0002_initial.py +++ b/payments/migrations/0002_initial.py @@ -10,32 +10,42 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('core', '0002_initial'), - ('payments', '0001_initial'), + ("core", "0002_initial"), + ("payments", "0001_initial"), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.AddField( - model_name='balance', - name='user', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='payments_balance', - to=settings.AUTH_USER_MODEL, blank=True, null=True), + model_name="balance", + name="user", + field=models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + related_name="payments_balance", + to=settings.AUTH_USER_MODEL, + blank=True, + null=True, + ), ), migrations.AddField( - model_name='transaction', - name='balance', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='payments.balance'), + model_name="transaction", + name="balance", + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="payments.balance"), ), migrations.AddField( - model_name='transaction', - name='order', - field=models.ForeignKey(blank=True, help_text='order to process after paid', null=True, - on_delete=django.db.models.deletion.CASCADE, related_name='payments_transactions', - to='core.order'), + model_name="transaction", + name="order", + field=models.ForeignKey( + blank=True, + help_text="order to process after paid", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="payments_transactions", + to="core.order", + ), ), migrations.AddIndex( - model_name='transaction', - index=django.contrib.postgres.indexes.GinIndex(fields=['process'], name='payments_tr_process_d5b008_gin'), + model_name="transaction", + index=django.contrib.postgres.indexes.GinIndex(fields=["process"], name="payments_tr_process_d5b008_gin"), ), ] diff --git a/payments/migrations/0003_alter_transaction_balance.py b/payments/migrations/0003_alter_transaction_balance.py index ea6bdece..029e2448 100644 --- a/payments/migrations/0003_alter_transaction_balance.py +++ b/payments/migrations/0003_alter_transaction_balance.py @@ -5,15 +5,20 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('payments', '0002_initial'), + ("payments", "0002_initial"), ] operations = [ migrations.AlterField( - model_name='transaction', - name='balance', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='transactions', to='payments.balance'), + model_name="transaction", + name="balance", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="transactions", + to="payments.balance", + ), ), ] diff --git a/payments/migrations/0004_alter_transaction_payment_method.py b/payments/migrations/0004_alter_transaction_payment_method.py index 241ecc4a..978c5214 100644 --- a/payments/migrations/0004_alter_transaction_payment_method.py +++ b/payments/migrations/0004_alter_transaction_payment_method.py @@ -4,15 +4,14 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('payments', '0003_alter_transaction_balance'), + ("payments", "0003_alter_transaction_balance"), ] operations = [ migrations.AlterField( - model_name='transaction', - name='payment_method', + model_name="transaction", + name="payment_method", field=models.CharField(blank=True, max_length=20, null=True), ), ] diff --git a/payments/models.py b/payments/models.py index 14eeeaaf..6678715b 100644 --- a/payments/models.py +++ b/payments/models.py @@ -7,13 +7,11 @@ from core.abstract import NiceModel class Transaction(NiceModel): - amount: float = FloatField(null=False, blank=False) # type: ignore - balance: "Balance" = ForeignKey( - "payments.Balance", on_delete=CASCADE, blank=True, null=True, related_name="transactions" - ) # type: ignore - currency: str = CharField(max_length=3, null=False, blank=False) # type: ignore - payment_method: str = CharField(max_length=20, null=True, blank=True) # type: ignore - order = ForeignKey( # type: ignore + amount = FloatField(null=False, blank=False) + balance = ForeignKey("payments.Balance", on_delete=CASCADE, blank=True, null=True, related_name="transactions") + currency = CharField(max_length=3, null=False, blank=False) + payment_method = CharField(max_length=20, null=True, blank=True) + order = ForeignKey( "core.Order", on_delete=CASCADE, blank=True, @@ -21,7 +19,7 @@ class Transaction(NiceModel): help_text=_("order to process after paid"), related_name="payments_transactions", ) - process: dict = JSONField(verbose_name=_("processing details"), default=dict) # type: ignore + process = JSONField(verbose_name=_("processing details"), default=dict) def __str__(self): return f"{self.balance.user.email} | {self.amount}" @@ -48,8 +46,8 @@ class Transaction(NiceModel): class Balance(NiceModel): - amount: float = FloatField(null=False, blank=False, default=0) # type: ignore - user = OneToOneField( # type: ignore + amount = FloatField(null=False, blank=False, default=0) + user = OneToOneField( to="vibes_auth.User", on_delete=CASCADE, blank=True, null=True, related_name="payments_balance" ) transactions: QuerySet["Transaction"] diff --git a/payments/serializers.py b/payments/serializers.py index 47f953a0..faa92d4c 100644 --- a/payments/serializers.py +++ b/payments/serializers.py @@ -19,11 +19,11 @@ class TransactionProcessSerializer(ModelSerializer): order_hr_id = SerializerMethodField(read_only=True, required=False) order_uuid = SerializerMethodField(read_only=True, required=False) - def get_order_hr_id(self, obj: Transaction): - return obj.order.human_readable_id if obj.order else None # type: ignore + def get_order_hr_id(self, obj: Transaction) -> str | None: + return obj.order.human_readable_id if obj.order else None - def get_order_uuid(self, obj: Transaction): - return obj.order.uuid if obj.order else None # type: ignore + def get_order_uuid(self, obj: Transaction) -> str | None: + return str(obj.order.uuid) if obj.order else None class Meta: model = Transaction diff --git a/payments/signals.py b/payments/signals.py index 7f94297a..9e9078b1 100644 --- a/payments/signals.py +++ b/payments/signals.py @@ -1,3 +1,6 @@ +import logging +import traceback + from django.db.models.signals import post_save from django.dispatch import receiver @@ -6,6 +9,8 @@ from payments.models import Balance, Transaction from payments.utils.emailing import balance_deposit_email from vibes_auth.models import User +logger = logging.getLogger("django") + @receiver(post_save, sender=User) def create_balance_on_user_creation_signal(instance, created, **_kwargs): @@ -17,12 +22,19 @@ def create_balance_on_user_creation_signal(instance, created, **_kwargs): def process_transaction_changes(instance, created, **_kwargs): if created: try: - gateway = AbstractGateway() + match instance.process.get("gateway", "default"): + case "gateway": + gateway = AbstractGateway() + case "default": + gateway = AbstractGateway() + case _: + gateway = AbstractGateway() gateway.process_transaction(instance) - except Exception as e: # noqa: - instance.process = {"status": "NOGATEWAY", "error": str(e)} + except Exception as e: + instance.process = {"status": "ERRORED", "error": str(e)} + logger.error(f"Error processing transaction {instance.uuid}: {e}\n{traceback.format_exc()}") if not created: - status = instance.process.get("status", "").lower() + status = str(instance.process.get("status", "")).lower() success = instance.process.get("success", False) if ("success" in status or success) and (instance.process.get("notify", False)): diff --git a/payments/templates/balance_deposit_email.html b/payments/templates/balance_deposit_email.html index 509d0c06..004d95ce 100644 --- a/payments/templates/balance_deposit_email.html +++ b/payments/templates/balance_deposit_email.html @@ -1,5 +1,4 @@ {% load tz static i18n filters conditions %} - @@ -61,12 +60,6 @@ color: #888; } - .order-table { - width: 100%; - margin-top: 20px; - border-collapse: collapse; - } - .order-table th, .order-table td { border: 1px solid #ddd; padding: 8px; @@ -91,7 +84,7 @@
diff --git a/payments/urls.py b/payments/urls.py index 6f703c4a..4c567fde 100644 --- a/payments/urls.py +++ b/payments/urls.py @@ -4,6 +4,8 @@ from rest_framework.routers import DefaultRouter from payments.views import CallbackAPIView, DepositView from payments.viewsets import TransactionViewSet +app_name = "payments" + payment_router = DefaultRouter() payment_router.register(prefix=r"transactions", viewset=TransactionViewSet, basename="transactions") diff --git a/payments/utils/emailing.py b/payments/utils/emailing.py index d2a39266..34df0767 100644 --- a/payments/utils/emailing.py +++ b/payments/utils/emailing.py @@ -6,19 +6,23 @@ from django.core import mail from django.core.mail import EmailMessage from django.template.loader import render_to_string from django.utils.translation import activate +from django.utils.translation import gettext_lazy as _ from core.utils.constance import set_email_settings from payments.models import Transaction -@shared_task +@shared_task(queue="default") def balance_deposit_email(transaction_pk: str) -> tuple[bool, str]: try: transaction = Transaction.objects.get(pk=transaction_pk) except Transaction.DoesNotExist: return False, f"Transaction not found with the given pk: {transaction_pk}" - activate(transaction.balance.user.language) # type: ignore + if not transaction.balance or not transaction.balance.user: + return False, f"Balance not found for the given transaction pk: {transaction_pk}" + + activate(transaction.balance.user.language) set_email_settings() connection = mail.get_connection() @@ -30,17 +34,17 @@ def balance_deposit_email(transaction_pk: str) -> tuple[bool, str]: context={ "amount": transaction.amount, "balance": transaction.balance.amount, - "user_first_name": transaction.balance.user.first_name, # type: ignore + "user_first_name": transaction.balance.user.first_name, "project_name": config.PROJECT_NAME, "contact_email": config.EMAIL_FROM, "today": datetime.today(), }, ), - to=[transaction.balance.user.email], # type: ignore + to=[transaction.balance.user.email], from_email=f"{config.PROJECT_NAME} <{config.EMAIL_FROM}>", connection=connection, ) email.content_subtype = "html" email.send() - return True, str(order.uuid) + return True, str(transaction_pk) diff --git a/payments/views.py b/payments/views.py index 9d3a1c6b..ef83ba09 100644 --- a/payments/views.py +++ b/payments/views.py @@ -11,11 +11,27 @@ from payments.gateways import UnknownGatewayError from payments.models import Transaction from payments.serializers import DepositSerializer, TransactionProcessSerializer -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") @extend_schema_view(**DEPOSIT_SCHEMA) class DepositView(APIView): + """Handles deposit operations. + + This class provides an API endpoint to handle deposit transactions. + It supports the creation of a deposit transaction after validating the + provided data. If the user is not authenticated, an appropriate response + is returned. On successful validation and execution, a response + with the transaction details is provided. + + Attributes: + No attributes are declared at the class-level for this view. + + Methods: + post: Processes the deposit request, validates the request data, ensures + user authentication, and creates a transaction. + """ + def post(self, request, *args, **kwargs): logger.debug(request.__dict__) serializer = DepositSerializer(data=request.data) @@ -33,8 +49,26 @@ class DepositView(APIView): @extend_schema(exclude=True) class CallbackAPIView(APIView): + """ + Handles incoming callback requests to the API. + + This class processes and routes incoming HTTP POST requests to the appropriate + gateway handler based on the provided gateway parameter. It is designed to handle + callback events coming from external systems and provide an appropriate HTTP response + indicating success or failure. + + Attributes: + No additional attributes are defined for this class beyond what is + inherited from APIView. + + Methods: + post(request, *args, **kwargs): Processes POST requests and routes them + based on the specified gateway. Handles exceptions gracefully by returning + a server error response if an unknown gateway or other issues occur. + """ + def post(self, request, *args, **kwargs): - logger.debug(request.__dict__) + logger.debug(f"{request.__dict__}\n") try: gateway = kwargs.get("gateway", "") # noinspection PyUnreachableCode diff --git a/payments/viewsets.py b/payments/viewsets.py index 0b7a141c..3342cecc 100644 --- a/payments/viewsets.py +++ b/payments/viewsets.py @@ -5,5 +5,21 @@ from payments.serializers import TransactionSerializer class TransactionViewSet(ReadOnlyModelViewSet): + """ + ViewSet for handling read-only operations on the Transaction model. + + This class provides a read-only interface for interacting with transaction + data. It uses the TransactionSerializer for serializing and deserializing + the data. The class ensures that only authorized users, who meet specific + permissions, can access the transactions. + + Attributes: + serializer_class: Specifies the serializer class to be used for + serializing transaction data. + permission_classes: A tuple specifying the permissions required to access + the data. Includes custom permissions to restrict access based + on ownership and other criteria. + """ + serializer_class = TransactionSerializer permission_classes = (EvibesPermission, IsOwner) diff --git a/poetry.lock b/poetry.lock index 7b663f20..e2edbd85 100644 --- a/poetry.lock +++ b/poetry.lock @@ -727,13 +727,13 @@ click = ">=7" [[package]] name = "click-plugins" -version = "1.1.1" +version = "1.1.1.2" description = "An extension module for click to enable registering CLI commands via setuptools entry-points." optional = false python-versions = "*" files = [ - {file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"}, - {file = "click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8"}, + {file = "click_plugins-1.1.1.2-py2.py3-none-any.whl", hash = "sha256:008d65743833ffc1f5417bf0e78e8d2c23aab04d9745ba817bd3e71b0feb6aa6"}, + {file = "click_plugins-1.1.1.2.tar.gz", hash = "sha256:d7af3984a99d243c131aa1a828331e7630f4a88a9741fd05c927b204bcf92261"}, ] [package.dependencies] @@ -1135,20 +1135,6 @@ files = [ asgiref = ">=3.6" django = ">=4.2" -[[package]] -name = "django-daisy" -version = "1.0.26" -description = "A modern Django dashboard built with DaisyUI" -optional = false -python-versions = "*" -files = [ - {file = "django_daisy-1.0.26-py3-none-any.whl", hash = "sha256:3c2dd94264beded68f8ed3399f919bd0ae29cb93f03badb7b5694dc6f4736ddb"}, - {file = "django_daisy-1.0.26.tar.gz", hash = "sha256:6fbafb5c4d15f0ca6b5d724e98c731e647a940c0270636ef363fc09ce1fa78cb"}, -] - -[package.dependencies] -Django = ">=3.2" - [[package]] name = "django-dbbackup" version = "4.3.0" @@ -1259,6 +1245,20 @@ files = [ {file = "django_hosts-6.0-py3-none-any.whl", hash = "sha256:34a97a183b3fb8a00de3e0a8af5355a25ff5203019d2e213edd8f12c330cc303"}, ] +[[package]] +name = "django-jazzmin" +version = "3.0.1" +description = "Drop-in theme for django admin, that utilises AdminLTE 3 & Bootstrap 4 to make yo' admin look jazzy" +optional = false +python-versions = ">=3.8" +files = [ + {file = "django_jazzmin-3.0.1-py3-none-any.whl", hash = "sha256:12a0a4c1d4fd09c2eef22acf6a1f03112b515ba695c59faa8ea80efc81c1f21b"}, + {file = "django_jazzmin-3.0.1.tar.gz", hash = "sha256:67ae148bade41267a09ca8e4352ddefa6121795ebbac238bb9a6564ff841eb1b"}, +] + +[package.dependencies] +django = ">=4.2" + [[package]] name = "django-js-asset" version = "3.1.2" @@ -1644,6 +1644,17 @@ dev = ["Django (>=1.6)", "djangorestframework (>=2.4.3)", "flake8", "mkdocs (>=0 docs = ["mkdocs (>=0.11.1)"] tests = ["Django (>=1.6)", "djangorestframework (>=2.4.3)", "flake8", "pytest", "pytest-django"] +[[package]] +name = "docutils" +version = "0.21.2" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.9" +files = [ + {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, + {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, +] + [[package]] name = "drf-spectacular" version = "0.28.0" @@ -1670,13 +1681,13 @@ sidecar = ["drf-spectacular-sidecar"] [[package]] name = "drf-spectacular-sidecar" -version = "2025.6.1" +version = "2025.7.1" description = "Serve self-contained distribution builds of Swagger UI and Redoc with Django" optional = false python-versions = ">=3.6" files = [ - {file = "drf_spectacular_sidecar-2025.6.1-py3-none-any.whl", hash = "sha256:c7c4768c03faa3d2f7afacd1464f67732e7d6866d2cf2e8f649175c27318745c"}, - {file = "drf_spectacular_sidecar-2025.6.1.tar.gz", hash = "sha256:ee6752c73d712265a61b9e2ca6f71c3b2bd89f30f39cf9f8cda98e7f371fcbcf"}, + {file = "drf_spectacular_sidecar-2025.7.1-py3-none-any.whl", hash = "sha256:efe33ba696ba25f28c32ead75b56e3ef68f167b9ed7468f8d16322bfe8e304e7"}, + {file = "drf_spectacular_sidecar-2025.7.1.tar.gz", hash = "sha256:03b4a9f2062115f69ce24509d855b180244d58ef45edd67ea8bcb214c7021e10"}, ] [package.dependencies] @@ -2114,13 +2125,13 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio [[package]] name = "ipython" -version = "9.3.0" +version = "9.4.0" description = "IPython: Productive Interactive Computing" optional = true python-versions = ">=3.11" files = [ - {file = "ipython-9.3.0-py3-none-any.whl", hash = "sha256:1a0b6dd9221a1f5dddf725b57ac0cb6fddc7b5f470576231ae9162b9b3455a04"}, - {file = "ipython-9.3.0.tar.gz", hash = "sha256:79eb896f9f23f50ad16c3bc205f686f6e030ad246cc309c6279a242b14afe9d8"}, + {file = "ipython-9.4.0-py3-none-any.whl", hash = "sha256:25850f025a446d9b359e8d296ba175a36aedd32e83ca9b5060430fe16801f066"}, + {file = "ipython-9.4.0.tar.gz", hash = "sha256:c033c6d4e7914c3d9768aabe76bbe87ba1dc66a92a05db6bfa1125d81f2ee270"}, ] [package.dependencies] @@ -2590,13 +2601,13 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> [[package]] name = "jupyterlab" -version = "4.4.3" +version = "4.4.4" description = "JupyterLab computational environment" optional = true python-versions = ">=3.9" files = [ - {file = "jupyterlab-4.4.3-py3-none-any.whl", hash = "sha256:164302f6d4b6c44773dfc38d585665a4db401a16e5296c37df5cba63904fbdea"}, - {file = "jupyterlab-4.4.3.tar.gz", hash = "sha256:a94c32fd7f8b93e82a49dc70a6ec45a5c18281ca2a7228d12765e4e210e5bca2"}, + {file = "jupyterlab-4.4.4-py3-none-any.whl", hash = "sha256:711611e4f59851152eb93316c3547c3ec6291f16bb455f1f4fa380d25637e0dd"}, + {file = "jupyterlab-4.4.4.tar.gz", hash = "sha256:163fee1ef702e0a057f75d2eed3ed1da8a986d59eb002cbeb6f0c2779e6cd153"}, ] [package.dependencies] @@ -2705,143 +2716,86 @@ zookeeper = ["kazoo (>=2.8.0)"] [[package]] name = "lxml" -version = "5.4.0" +version = "6.0.0" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "lxml-5.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e7bc6df34d42322c5289e37e9971d6ed114e3776b45fa879f734bded9d1fea9c"}, - {file = "lxml-5.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6854f8bd8a1536f8a1d9a3655e6354faa6406621cf857dc27b681b69860645c7"}, - {file = "lxml-5.4.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:696ea9e87442467819ac22394ca36cb3d01848dad1be6fac3fb612d3bd5a12cf"}, - {file = "lxml-5.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ef80aeac414f33c24b3815ecd560cee272786c3adfa5f31316d8b349bfade28"}, - {file = "lxml-5.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b9c2754cef6963f3408ab381ea55f47dabc6f78f4b8ebb0f0b25cf1ac1f7609"}, - {file = "lxml-5.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7a62cc23d754bb449d63ff35334acc9f5c02e6dae830d78dab4dd12b78a524f4"}, - {file = "lxml-5.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f82125bc7203c5ae8633a7d5d20bcfdff0ba33e436e4ab0abc026a53a8960b7"}, - {file = "lxml-5.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:b67319b4aef1a6c56576ff544b67a2a6fbd7eaee485b241cabf53115e8908b8f"}, - {file = "lxml-5.4.0-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:a8ef956fce64c8551221f395ba21d0724fed6b9b6242ca4f2f7beb4ce2f41997"}, - {file = "lxml-5.4.0-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:0a01ce7d8479dce84fc03324e3b0c9c90b1ece9a9bb6a1b6c9025e7e4520e78c"}, - {file = "lxml-5.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:91505d3ddebf268bb1588eb0f63821f738d20e1e7f05d3c647a5ca900288760b"}, - {file = "lxml-5.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a3bcdde35d82ff385f4ede021df801b5c4a5bcdfb61ea87caabcebfc4945dc1b"}, - {file = "lxml-5.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:aea7c06667b987787c7d1f5e1dfcd70419b711cdb47d6b4bb4ad4b76777a0563"}, - {file = "lxml-5.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a7fb111eef4d05909b82152721a59c1b14d0f365e2be4c742a473c5d7372f4f5"}, - {file = "lxml-5.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:43d549b876ce64aa18b2328faff70f5877f8c6dede415f80a2f799d31644d776"}, - {file = "lxml-5.4.0-cp310-cp310-win32.whl", hash = "sha256:75133890e40d229d6c5837b0312abbe5bac1c342452cf0e12523477cd3aa21e7"}, - {file = "lxml-5.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:de5b4e1088523e2b6f730d0509a9a813355b7f5659d70eb4f319c76beea2e250"}, - {file = "lxml-5.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:98a3912194c079ef37e716ed228ae0dcb960992100461b704aea4e93af6b0bb9"}, - {file = "lxml-5.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0ea0252b51d296a75f6118ed0d8696888e7403408ad42345d7dfd0d1e93309a7"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b92b69441d1bd39f4940f9eadfa417a25862242ca2c396b406f9272ef09cdcaa"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20e16c08254b9b6466526bc1828d9370ee6c0d60a4b64836bc3ac2917d1e16df"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7605c1c32c3d6e8c990dd28a0970a3cbbf1429d5b92279e37fda05fb0c92190e"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ecf4c4b83f1ab3d5a7ace10bafcb6f11df6156857a3c418244cef41ca9fa3e44"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cef4feae82709eed352cd7e97ae062ef6ae9c7b5dbe3663f104cd2c0e8d94ba"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:df53330a3bff250f10472ce96a9af28628ff1f4efc51ccba351a8820bca2a8ba"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:aefe1a7cb852fa61150fcb21a8c8fcea7b58c4cb11fbe59c97a0a4b31cae3c8c"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:ef5a7178fcc73b7d8c07229e89f8eb45b2908a9238eb90dcfc46571ccf0383b8"}, - {file = "lxml-5.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d2ed1b3cb9ff1c10e6e8b00941bb2e5bb568b307bfc6b17dffbbe8be5eecba86"}, - {file = "lxml-5.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:72ac9762a9f8ce74c9eed4a4e74306f2f18613a6b71fa065495a67ac227b3056"}, - {file = "lxml-5.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f5cb182f6396706dc6cc1896dd02b1c889d644c081b0cdec38747573db88a7d7"}, - {file = "lxml-5.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:3a3178b4873df8ef9457a4875703488eb1622632a9cee6d76464b60e90adbfcd"}, - {file = "lxml-5.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e094ec83694b59d263802ed03a8384594fcce477ce484b0cbcd0008a211ca751"}, - {file = "lxml-5.4.0-cp311-cp311-win32.whl", hash = "sha256:4329422de653cdb2b72afa39b0aa04252fca9071550044904b2e7036d9d97fe4"}, - {file = "lxml-5.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd3be6481ef54b8cfd0e1e953323b7aa9d9789b94842d0e5b142ef4bb7999539"}, - {file = "lxml-5.4.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b5aff6f3e818e6bdbbb38e5967520f174b18f539c2b9de867b1e7fde6f8d95a4"}, - {file = "lxml-5.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:942a5d73f739ad7c452bf739a62a0f83e2578afd6b8e5406308731f4ce78b16d"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:460508a4b07364d6abf53acaa0a90b6d370fafde5693ef37602566613a9b0779"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:529024ab3a505fed78fe3cc5ddc079464e709f6c892733e3f5842007cec8ac6e"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ca56ebc2c474e8f3d5761debfd9283b8b18c76c4fc0967b74aeafba1f5647f9"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a81e1196f0a5b4167a8dafe3a66aa67c4addac1b22dc47947abd5d5c7a3f24b5"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00b8686694423ddae324cf614e1b9659c2edb754de617703c3d29ff568448df5"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:c5681160758d3f6ac5b4fea370495c48aac0989d6a0f01bb9a72ad8ef5ab75c4"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:2dc191e60425ad70e75a68c9fd90ab284df64d9cd410ba8d2b641c0c45bc006e"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:67f779374c6b9753ae0a0195a892a1c234ce8416e4448fe1e9f34746482070a7"}, - {file = "lxml-5.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:79d5bfa9c1b455336f52343130b2067164040604e41f6dc4d8313867ed540079"}, - {file = "lxml-5.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3d3c30ba1c9b48c68489dc1829a6eede9873f52edca1dda900066542528d6b20"}, - {file = "lxml-5.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1af80c6316ae68aded77e91cd9d80648f7dd40406cef73df841aa3c36f6907c8"}, - {file = "lxml-5.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4d885698f5019abe0de3d352caf9466d5de2baded00a06ef3f1216c1a58ae78f"}, - {file = "lxml-5.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aea53d51859b6c64e7c51d522c03cc2c48b9b5d6172126854cc7f01aa11f52bc"}, - {file = "lxml-5.4.0-cp312-cp312-win32.whl", hash = "sha256:d90b729fd2732df28130c064aac9bb8aff14ba20baa4aee7bd0795ff1187545f"}, - {file = "lxml-5.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1dc4ca99e89c335a7ed47d38964abcb36c5910790f9bd106f2a8fa2ee0b909d2"}, - {file = "lxml-5.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:773e27b62920199c6197130632c18fb7ead3257fce1ffb7d286912e56ddb79e0"}, - {file = "lxml-5.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ce9c671845de9699904b1e9df95acfe8dfc183f2310f163cdaa91a3535af95de"}, - {file = "lxml-5.4.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9454b8d8200ec99a224df8854786262b1bd6461f4280064c807303c642c05e76"}, - {file = "lxml-5.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cccd007d5c95279e529c146d095f1d39ac05139de26c098166c4beb9374b0f4d"}, - {file = "lxml-5.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0fce1294a0497edb034cb416ad3e77ecc89b313cff7adbee5334e4dc0d11f422"}, - {file = "lxml-5.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:24974f774f3a78ac12b95e3a20ef0931795ff04dbb16db81a90c37f589819551"}, - {file = "lxml-5.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:497cab4d8254c2a90bf988f162ace2ddbfdd806fce3bda3f581b9d24c852e03c"}, - {file = "lxml-5.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:e794f698ae4c5084414efea0f5cc9f4ac562ec02d66e1484ff822ef97c2cadff"}, - {file = "lxml-5.4.0-cp313-cp313-manylinux_2_28_ppc64le.whl", hash = "sha256:2c62891b1ea3094bb12097822b3d44b93fc6c325f2043c4d2736a8ff09e65f60"}, - {file = "lxml-5.4.0-cp313-cp313-manylinux_2_28_s390x.whl", hash = "sha256:142accb3e4d1edae4b392bd165a9abdee8a3c432a2cca193df995bc3886249c8"}, - {file = "lxml-5.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1a42b3a19346e5601d1b8296ff6ef3d76038058f311902edd574461e9c036982"}, - {file = "lxml-5.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4291d3c409a17febf817259cb37bc62cb7eb398bcc95c1356947e2871911ae61"}, - {file = "lxml-5.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4f5322cf38fe0e21c2d73901abf68e6329dc02a4994e483adbcf92b568a09a54"}, - {file = "lxml-5.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0be91891bdb06ebe65122aa6bf3fc94489960cf7e03033c6f83a90863b23c58b"}, - {file = "lxml-5.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:15a665ad90054a3d4f397bc40f73948d48e36e4c09f9bcffc7d90c87410e478a"}, - {file = "lxml-5.4.0-cp313-cp313-win32.whl", hash = "sha256:d5663bc1b471c79f5c833cffbc9b87d7bf13f87e055a5c86c363ccd2348d7e82"}, - {file = "lxml-5.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:bcb7a1096b4b6b24ce1ac24d4942ad98f983cd3810f9711bcd0293f43a9d8b9f"}, - {file = "lxml-5.4.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7be701c24e7f843e6788353c055d806e8bd8466b52907bafe5d13ec6a6dbaecd"}, - {file = "lxml-5.4.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb54f7c6bafaa808f27166569b1511fc42701a7713858dddc08afdde9746849e"}, - {file = "lxml-5.4.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97dac543661e84a284502e0cf8a67b5c711b0ad5fb661d1bd505c02f8cf716d7"}, - {file = "lxml-5.4.0-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:c70e93fba207106cb16bf852e421c37bbded92acd5964390aad07cb50d60f5cf"}, - {file = "lxml-5.4.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9c886b481aefdf818ad44846145f6eaf373a20d200b5ce1a5c8e1bc2d8745410"}, - {file = "lxml-5.4.0-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:fa0e294046de09acd6146be0ed6727d1f42ded4ce3ea1e9a19c11b6774eea27c"}, - {file = "lxml-5.4.0-cp36-cp36m-win32.whl", hash = "sha256:61c7bbf432f09ee44b1ccaa24896d21075e533cd01477966a5ff5a71d88b2f56"}, - {file = "lxml-5.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7ce1a171ec325192c6a636b64c94418e71a1964f56d002cc28122fceff0b6121"}, - {file = "lxml-5.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:795f61bcaf8770e1b37eec24edf9771b307df3af74d1d6f27d812e15a9ff3872"}, - {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:29f451a4b614a7b5b6c2e043d7b64a15bd8304d7e767055e8ab68387a8cacf4e"}, - {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:891f7f991a68d20c75cb13c5c9142b2a3f9eb161f1f12a9489c82172d1f133c0"}, - {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4aa412a82e460571fad592d0f93ce9935a20090029ba08eca05c614f99b0cc92"}, - {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:ac7ba71f9561cd7d7b55e1ea5511543c0282e2b6450f122672a2694621d63b7e"}, - {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:c5d32f5284012deaccd37da1e2cd42f081feaa76981f0eaa474351b68df813c5"}, - {file = "lxml-5.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:ce31158630a6ac85bddd6b830cffd46085ff90498b397bd0a259f59d27a12188"}, - {file = "lxml-5.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:31e63621e073e04697c1b2d23fcb89991790eef370ec37ce4d5d469f40924ed6"}, - {file = "lxml-5.4.0-cp37-cp37m-win32.whl", hash = "sha256:be2ba4c3c5b7900246a8f866580700ef0d538f2ca32535e991027bdaba944063"}, - {file = "lxml-5.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:09846782b1ef650b321484ad429217f5154da4d6e786636c38e434fa32e94e49"}, - {file = "lxml-5.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eaf24066ad0b30917186420d51e2e3edf4b0e2ea68d8cd885b14dc8afdcf6556"}, - {file = "lxml-5.4.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b31a3a77501d86d8ade128abb01082724c0dfd9524f542f2f07d693c9f1175f"}, - {file = "lxml-5.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e108352e203c7afd0eb91d782582f00a0b16a948d204d4dec8565024fafeea5"}, - {file = "lxml-5.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a11a96c3b3f7551c8a8109aa65e8594e551d5a84c76bf950da33d0fb6dfafab7"}, - {file = "lxml-5.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:ca755eebf0d9e62d6cb013f1261e510317a41bf4650f22963474a663fdfe02aa"}, - {file = "lxml-5.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:4cd915c0fb1bed47b5e6d6edd424ac25856252f09120e3e8ba5154b6b921860e"}, - {file = "lxml-5.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:226046e386556a45ebc787871d6d2467b32c37ce76c2680f5c608e25823ffc84"}, - {file = "lxml-5.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:b108134b9667bcd71236c5a02aad5ddd073e372fb5d48ea74853e009fe38acb6"}, - {file = "lxml-5.4.0-cp38-cp38-win32.whl", hash = "sha256:1320091caa89805df7dcb9e908add28166113dcd062590668514dbd510798c88"}, - {file = "lxml-5.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:073eb6dcdf1f587d9b88c8c93528b57eccda40209cf9be549d469b942b41d70b"}, - {file = "lxml-5.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bda3ea44c39eb74e2488297bb39d47186ed01342f0022c8ff407c250ac3f498e"}, - {file = "lxml-5.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9ceaf423b50ecfc23ca00b7f50b64baba85fb3fb91c53e2c9d00bc86150c7e40"}, - {file = "lxml-5.4.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:664cdc733bc87449fe781dbb1f309090966c11cc0c0cd7b84af956a02a8a4729"}, - {file = "lxml-5.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67ed8a40665b84d161bae3181aa2763beea3747f748bca5874b4af4d75998f87"}, - {file = "lxml-5.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b4a3bd174cc9cdaa1afbc4620c049038b441d6ba07629d89a83b408e54c35cd"}, - {file = "lxml-5.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:b0989737a3ba6cf2a16efb857fb0dfa20bc5c542737fddb6d893fde48be45433"}, - {file = "lxml-5.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:dc0af80267edc68adf85f2a5d9be1cdf062f973db6790c1d065e45025fa26140"}, - {file = "lxml-5.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:639978bccb04c42677db43c79bdaa23785dc7f9b83bfd87570da8207872f1ce5"}, - {file = "lxml-5.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5a99d86351f9c15e4a901fc56404b485b1462039db59288b203f8c629260a142"}, - {file = "lxml-5.4.0-cp39-cp39-win32.whl", hash = "sha256:3e6d5557989cdc3ebb5302bbdc42b439733a841891762ded9514e74f60319ad6"}, - {file = "lxml-5.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:a8c9b7f16b63e65bbba889acb436a1034a82d34fa09752d754f88d708eca80e1"}, - {file = "lxml-5.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1b717b00a71b901b4667226bba282dd462c42ccf618ade12f9ba3674e1fabc55"}, - {file = "lxml-5.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27a9ded0f0b52098ff89dd4c418325b987feed2ea5cc86e8860b0f844285d740"}, - {file = "lxml-5.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b7ce10634113651d6f383aa712a194179dcd496bd8c41e191cec2099fa09de5"}, - {file = "lxml-5.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:53370c26500d22b45182f98847243efb518d268374a9570409d2e2276232fd37"}, - {file = "lxml-5.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c6364038c519dffdbe07e3cf42e6a7f8b90c275d4d1617a69bb59734c1a2d571"}, - {file = "lxml-5.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b12cb6527599808ada9eb2cd6e0e7d3d8f13fe7bbb01c6311255a15ded4c7ab4"}, - {file = "lxml-5.4.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5f11a1526ebd0dee85e7b1e39e39a0cc0d9d03fb527f56d8457f6df48a10dc0c"}, - {file = "lxml-5.4.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48b4afaf38bf79109bb060d9016fad014a9a48fb244e11b94f74ae366a64d252"}, - {file = "lxml-5.4.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de6f6bb8a7840c7bf216fb83eec4e2f79f7325eca8858167b68708b929ab2172"}, - {file = "lxml-5.4.0-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5cca36a194a4eb4e2ed6be36923d3cffd03dcdf477515dea687185506583d4c9"}, - {file = "lxml-5.4.0-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b7c86884ad23d61b025989d99bfdd92a7351de956e01c61307cb87035960bcb1"}, - {file = "lxml-5.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:53d9469ab5460402c19553b56c3648746774ecd0681b1b27ea74d5d8a3ef5590"}, - {file = "lxml-5.4.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:56dbdbab0551532bb26c19c914848d7251d73edb507c3079d6805fa8bba5b706"}, - {file = "lxml-5.4.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14479c2ad1cb08b62bb941ba8e0e05938524ee3c3114644df905d2331c76cd57"}, - {file = "lxml-5.4.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32697d2ea994e0db19c1df9e40275ffe84973e4232b5c274f47e7c1ec9763cdd"}, - {file = "lxml-5.4.0-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:24f6df5f24fc3385f622c0c9d63fe34604893bc1a5bdbb2dbf5870f85f9a404a"}, - {file = "lxml-5.4.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:151d6c40bc9db11e960619d2bf2ec5829f0aaffb10b41dcf6ad2ce0f3c0b2325"}, - {file = "lxml-5.4.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4025bf2884ac4370a3243c5aa8d66d3cb9e15d3ddd0af2d796eccc5f0244390e"}, - {file = "lxml-5.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9459e6892f59ecea2e2584ee1058f5d8f629446eab52ba2305ae13a32a059530"}, - {file = "lxml-5.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47fb24cc0f052f0576ea382872b3fc7e1f7e3028e53299ea751839418ade92a6"}, - {file = "lxml-5.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50441c9de951a153c698b9b99992e806b71c1f36d14b154592580ff4a9d0d877"}, - {file = "lxml-5.4.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:ab339536aa798b1e17750733663d272038bf28069761d5be57cb4a9b0137b4f8"}, - {file = "lxml-5.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9776af1aad5a4b4a1317242ee2bea51da54b2a7b7b48674be736d463c999f37d"}, - {file = "lxml-5.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:63e7968ff83da2eb6fdda967483a7a023aa497d85ad8f05c3ad9b1f2e8c84987"}, - {file = "lxml-5.4.0.tar.gz", hash = "sha256:d12832e1dbea4be280b22fd0ea7c9b87f0d8fc51ba06e92dc62d52f804f78ebd"}, + {file = "lxml-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:35bc626eec405f745199200ccb5c6b36f202675d204aa29bb52e27ba2b71dea8"}, + {file = "lxml-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:246b40f8a4aec341cbbf52617cad8ab7c888d944bfe12a6abd2b1f6cfb6f6082"}, + {file = "lxml-6.0.0-cp310-cp310-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:2793a627e95d119e9f1e19720730472f5543a6d84c50ea33313ce328d870f2dd"}, + {file = "lxml-6.0.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e2030956cf4886b10be9a0285c6802e078ec2391e1dd7ff3eb509c2c95a69b76"}, + {file = "lxml-6.0.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d23854ecf381ab1facc8f353dcd9adeddef3652268ee75297c1164c987c11dc"}, + {file = "lxml-6.0.0-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:43fe5af2d590bf4691531b1d9a2495d7aab2090547eaacd224a3afec95706d76"}, + {file = "lxml-6.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74e748012f8c19b47f7d6321ac929a9a94ee92ef12bc4298c47e8b7219b26541"}, + {file = "lxml-6.0.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:43cfbb7db02b30ad3926e8fceaef260ba2fb7df787e38fa2df890c1ca7966c3b"}, + {file = "lxml-6.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:34190a1ec4f1e84af256495436b2d196529c3f2094f0af80202947567fdbf2e7"}, + {file = "lxml-6.0.0-cp310-cp310-win32.whl", hash = "sha256:5967fe415b1920a3877a4195e9a2b779249630ee49ece22021c690320ff07452"}, + {file = "lxml-6.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:f3389924581d9a770c6caa4df4e74b606180869043b9073e2cec324bad6e306e"}, + {file = "lxml-6.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:522fe7abb41309e9543b0d9b8b434f2b630c5fdaf6482bee642b34c8c70079c8"}, + {file = "lxml-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ee56288d0df919e4aac43b539dd0e34bb55d6a12a6562038e8d6f3ed07f9e36"}, + {file = "lxml-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b8dd6dd0e9c1992613ccda2bcb74fc9d49159dbe0f0ca4753f37527749885c25"}, + {file = "lxml-6.0.0-cp311-cp311-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:d7ae472f74afcc47320238b5dbfd363aba111a525943c8a34a1b657c6be934c3"}, + {file = "lxml-6.0.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f720a14aa102a38907c6d5030e3d66b3b680c3e6f6bc95473931ea3c00c59967"}, + {file = "lxml-6.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c2a5e8d207311a0170aca0eb6b160af91adc29ec121832e4ac151a57743a1e1e"}, + {file = "lxml-6.0.0-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:2dd1cc3ea7e60bfb31ff32cafe07e24839df573a5e7c2d33304082a5019bcd58"}, + {file = "lxml-6.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2cfcf84f1defed7e5798ef4f88aa25fcc52d279be731ce904789aa7ccfb7e8d2"}, + {file = "lxml-6.0.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:a52a4704811e2623b0324a18d41ad4b9fabf43ce5ff99b14e40a520e2190c851"}, + {file = "lxml-6.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c16304bba98f48a28ae10e32a8e75c349dd742c45156f297e16eeb1ba9287a1f"}, + {file = "lxml-6.0.0-cp311-cp311-win32.whl", hash = "sha256:f8d19565ae3eb956d84da3ef367aa7def14a2735d05bd275cd54c0301f0d0d6c"}, + {file = "lxml-6.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:b2d71cdefda9424adff9a3607ba5bbfc60ee972d73c21c7e3c19e71037574816"}, + {file = "lxml-6.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:8a2e76efbf8772add72d002d67a4c3d0958638696f541734304c7f28217a9cab"}, + {file = "lxml-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78718d8454a6e928470d511bf8ac93f469283a45c354995f7d19e77292f26108"}, + {file = "lxml-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:84ef591495ffd3f9dcabffd6391db7bb70d7230b5c35ef5148354a134f56f2be"}, + {file = "lxml-6.0.0-cp312-cp312-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:2930aa001a3776c3e2601cb8e0a15d21b8270528d89cc308be4843ade546b9ab"}, + {file = "lxml-6.0.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:390240baeb9f415a82eefc2e13285016f9c8b5ad71ec80574ae8fa9605093cd7"}, + {file = "lxml-6.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ca50bd612438258a91b5b3788c6621c1f05c8c478e7951899f492be42defc0da"}, + {file = "lxml-6.0.0-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:c24b8efd9c0f62bad0439283c2c795ef916c5a6b75f03c17799775c7ae3c0c9e"}, + {file = "lxml-6.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:afd27d8629ae94c5d863e32ab0e1d5590371d296b87dae0a751fb22bf3685741"}, + {file = "lxml-6.0.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:54c4855eabd9fc29707d30141be99e5cd1102e7d2258d2892314cf4c110726c3"}, + {file = "lxml-6.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:36531f81c8214e293097cd2b7873f178997dae33d3667caaae8bdfb9666b76c0"}, + {file = "lxml-6.0.0-cp312-cp312-win32.whl", hash = "sha256:690b20e3388a7ec98e899fd54c924e50ba6693874aa65ef9cb53de7f7de9d64a"}, + {file = "lxml-6.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:310b719b695b3dd442cdfbbe64936b2f2e231bb91d998e99e6f0daf991a3eba3"}, + {file = "lxml-6.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:8cb26f51c82d77483cdcd2b4a53cda55bbee29b3c2f3ddeb47182a2a9064e4eb"}, + {file = "lxml-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6da7cd4f405fd7db56e51e96bff0865b9853ae70df0e6720624049da76bde2da"}, + {file = "lxml-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b34339898bb556a2351a1830f88f751679f343eabf9cf05841c95b165152c9e7"}, + {file = "lxml-6.0.0-cp313-cp313-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:51a5e4c61a4541bd1cd3ba74766d0c9b6c12d6a1a4964ef60026832aac8e79b3"}, + {file = "lxml-6.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f4b481b6cc3a897adb4279216695150bbe7a44c03daba3c894f49d2037e0a24"}, + {file = "lxml-6.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae06fbab4f1bb7db4f7c8ca9897dc8db4447d1a2b9bee78474ad403437bcc29"}, + {file = "lxml-6.0.0-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:1fa377b827ca2023244a06554c6e7dc6828a10aaf74ca41965c5d8a4925aebb4"}, + {file = "lxml-6.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1676b56d48048a62ef77a250428d1f31f610763636e0784ba67a9740823988ca"}, + {file = "lxml-6.0.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:0e32698462aacc5c1cf6bdfebc9c781821b7e74c79f13e5ffc8bfe27c42b1abf"}, + {file = "lxml-6.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7488a43033c958637b1a08cddc9188eb06d3ad36582cebc7d4815980b47e27ef"}, + {file = "lxml-6.0.0-cp313-cp313-win32.whl", hash = "sha256:5fcd7d3b1d8ecb91445bd71b9c88bdbeae528fefee4f379895becfc72298d181"}, + {file = "lxml-6.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:2f34687222b78fff795feeb799a7d44eca2477c3d9d3a46ce17d51a4f383e32e"}, + {file = "lxml-6.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:21db1ec5525780fd07251636eb5f7acb84003e9382c72c18c542a87c416ade03"}, + {file = "lxml-6.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4eb114a0754fd00075c12648d991ec7a4357f9cb873042cc9a77bf3a7e30c9db"}, + {file = "lxml-6.0.0-cp38-cp38-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:7da298e1659e45d151b4028ad5c7974917e108afb48731f4ed785d02b6818994"}, + {file = "lxml-6.0.0-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63b634facdfbad421d4b61c90735688465d4ab3a8853ac22c76ccac2baf98d97"}, + {file = "lxml-6.0.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:e380e85b93f148ad28ac15f8117e2fd8e5437aa7732d65e260134f83ce67911b"}, + {file = "lxml-6.0.0-cp38-cp38-win32.whl", hash = "sha256:185efc2fed89cdd97552585c624d3c908f0464090f4b91f7d92f8ed2f3b18f54"}, + {file = "lxml-6.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:f97487996a39cb18278ca33f7be98198f278d0bc3c5d0fd4d7b3d63646ca3c8a"}, + {file = "lxml-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:85b14a4689d5cff426c12eefe750738648706ea2753b20c2f973b2a000d3d261"}, + {file = "lxml-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f64ccf593916e93b8d36ed55401bb7fe9c7d5de3180ce2e10b08f82a8f397316"}, + {file = "lxml-6.0.0-cp39-cp39-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:b372d10d17a701b0945f67be58fae4664fd056b85e0ff0fbc1e6c951cdbc0512"}, + {file = "lxml-6.0.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:048a930eb4572829604982e39a0c7289ab5dc8abc7fc9f5aabd6fbc08c154e93"}, + {file = "lxml-6.0.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c0b5fa5eda84057a4f1bbb4bb77a8c28ff20ae7ce211588d698ae453e13c6281"}, + {file = "lxml-6.0.0-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:c352fc8f36f7e9727db17adbf93f82499457b3d7e5511368569b4c5bd155a922"}, + {file = "lxml-6.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8db5dc617cb937ae17ff3403c3a70a7de9df4852a046f93e71edaec678f721d0"}, + {file = "lxml-6.0.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:2181e4b1d07dde53986023482673c0f1fba5178ef800f9ab95ad791e8bdded6a"}, + {file = "lxml-6.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b3c98d5b24c6095e89e03d65d5c574705be3d49c0d8ca10c17a8a4b5201b72f5"}, + {file = "lxml-6.0.0-cp39-cp39-win32.whl", hash = "sha256:04d67ceee6db4bcb92987ccb16e53bef6b42ced872509f333c04fb58a3315256"}, + {file = "lxml-6.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:e0b1520ef900e9ef62e392dd3d7ae4f5fa224d1dd62897a792cf353eb20b6cae"}, + {file = "lxml-6.0.0-cp39-cp39-win_arm64.whl", hash = "sha256:e35e8aaaf3981489f42884b59726693de32dabfc438ac10ef4eb3409961fd402"}, + {file = "lxml-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:dbdd7679a6f4f08152818043dbb39491d1af3332128b3752c3ec5cebc0011a72"}, + {file = "lxml-6.0.0-pp310-pypy310_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9ab542c91f5a47aaa58abdd8ea84b498e8e49fe4b883d67800017757a3eb78e8"}, + {file = "lxml-6.0.0-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:013090383863b72c62a702d07678b658fa2567aa58d373d963cca245b017e065"}, + {file = "lxml-6.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c86df1c9af35d903d2b52d22ea3e66db8058d21dc0f59842ca5deb0595921141"}, + {file = "lxml-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4337e4aec93b7c011f7ee2e357b0d30562edd1955620fdd4aeab6aacd90d43c5"}, + {file = "lxml-6.0.0-pp39-pypy39_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:17f090a9bc0ce8da51a5632092f98a7e7f84bca26f33d161a98b57f7fb0004ca"}, + {file = "lxml-6.0.0-pp39-pypy39_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9da022c14baeec36edfcc8daf0e281e2f55b950249a455776f0d1adeeada4734"}, + {file = "lxml-6.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a55da151d0b0c6ab176b4e761670ac0e2667817a1e0dadd04a01d0561a219349"}, + {file = "lxml-6.0.0.tar.gz", hash = "sha256:032e65120339d44cdc3efc326c9f660f5f7205f3a535c1fdbf898b29ea01fb72"}, ] [package.extras] @@ -2849,7 +2803,6 @@ cssselect = ["cssselect (>=0.7)"] html-clean = ["lxml_html_clean"] html5 = ["html5lib"] htmlsoup = ["BeautifulSoup4"] -source = ["Cython (>=3.0.11,<3.1.0)"] [[package]] name = "markdown" @@ -3174,18 +3127,18 @@ files = [ [[package]] name = "notebook" -version = "7.4.3" +version = "7.4.4" description = "Jupyter Notebook - A web-based notebook environment for interactive computing" optional = true python-versions = ">=3.8" files = [ - {file = "notebook-7.4.3-py3-none-any.whl", hash = "sha256:9cdeee954e04101cadb195d90e2ab62b7c9286c1d4f858bf3bb54e40df16c0c3"}, - {file = "notebook-7.4.3.tar.gz", hash = "sha256:a1567481cd3853f2610ee0ecf5dfa12bb508e878ee8f92152c134ef7f0568a76"}, + {file = "notebook-7.4.4-py3-none-any.whl", hash = "sha256:32840f7f777b6bff79bb101159336e9b332bdbfba1495b8739e34d1d65cbc1c0"}, + {file = "notebook-7.4.4.tar.gz", hash = "sha256:392fd501e266f2fb3466c6fcd3331163a2184968cb5c5accf90292e01dfe528c"}, ] [package.dependencies] jupyter-server = ">=2.4.0,<3" -jupyterlab = ">=4.4.3,<4.5" +jupyterlab = ">=4.4.4,<4.5" jupyterlab-server = ">=2.27.1,<3" notebook-shim = ">=0.2,<0.3" tornado = ">=6.2.0" @@ -4387,128 +4340,155 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "rpds-py" -version = "0.25.1" +version = "0.26.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.9" files = [ - {file = "rpds_py-0.25.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f4ad628b5174d5315761b67f212774a32f5bad5e61396d38108bd801c0a8f5d9"}, - {file = "rpds_py-0.25.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c742af695f7525e559c16f1562cf2323db0e3f0fbdcabdf6865b095256b2d40"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:605ffe7769e24b1800b4d024d24034405d9404f0bc2f55b6db3362cd34145a6f"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ccc6f3ddef93243538be76f8e47045b4aad7a66a212cd3a0f23e34469473d36b"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f70316f760174ca04492b5ab01be631a8ae30cadab1d1081035136ba12738cfa"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1dafef8df605fdb46edcc0bf1573dea0d6d7b01ba87f85cd04dc855b2b4479e"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0701942049095741a8aeb298a31b203e735d1c61f4423511d2b1a41dcd8a16da"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e87798852ae0b37c88babb7f7bbbb3e3fecc562a1c340195b44c7e24d403e380"}, - {file = "rpds_py-0.25.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3bcce0edc1488906c2d4c75c94c70a0417e83920dd4c88fec1078c94843a6ce9"}, - {file = "rpds_py-0.25.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e2f6a2347d3440ae789505693a02836383426249d5293541cd712e07e7aecf54"}, - {file = "rpds_py-0.25.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4fd52d3455a0aa997734f3835cbc4c9f32571345143960e7d7ebfe7b5fbfa3b2"}, - {file = "rpds_py-0.25.1-cp310-cp310-win32.whl", hash = "sha256:3f0b1798cae2bbbc9b9db44ee068c556d4737911ad53a4e5093d09d04b3bbc24"}, - {file = "rpds_py-0.25.1-cp310-cp310-win_amd64.whl", hash = "sha256:3ebd879ab996537fc510a2be58c59915b5dd63bccb06d1ef514fee787e05984a"}, - {file = "rpds_py-0.25.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5f048bbf18b1f9120685c6d6bb70cc1a52c8cc11bdd04e643d28d3be0baf666d"}, - {file = "rpds_py-0.25.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fbb0dbba559959fcb5d0735a0f87cdbca9e95dac87982e9b95c0f8f7ad10255"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4ca54b9cf9d80b4016a67a0193ebe0bcf29f6b0a96f09db942087e294d3d4c2"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ee3e26eb83d39b886d2cb6e06ea701bba82ef30a0de044d34626ede51ec98b0"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89706d0683c73a26f76a5315d893c051324d771196ae8b13e6ffa1ffaf5e574f"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2013ee878c76269c7b557a9a9c042335d732e89d482606990b70a839635feb7"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45e484db65e5380804afbec784522de84fa95e6bb92ef1bd3325d33d13efaebd"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:48d64155d02127c249695abb87d39f0faf410733428d499867606be138161d65"}, - {file = "rpds_py-0.25.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:048893e902132fd6548a2e661fb38bf4896a89eea95ac5816cf443524a85556f"}, - {file = "rpds_py-0.25.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0317177b1e8691ab5879f4f33f4b6dc55ad3b344399e23df2e499de7b10a548d"}, - {file = "rpds_py-0.25.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bffcf57826d77a4151962bf1701374e0fc87f536e56ec46f1abdd6a903354042"}, - {file = "rpds_py-0.25.1-cp311-cp311-win32.whl", hash = "sha256:cda776f1967cb304816173b30994faaf2fd5bcb37e73118a47964a02c348e1bc"}, - {file = "rpds_py-0.25.1-cp311-cp311-win_amd64.whl", hash = "sha256:dc3c1ff0abc91444cd20ec643d0f805df9a3661fcacf9c95000329f3ddf268a4"}, - {file = "rpds_py-0.25.1-cp311-cp311-win_arm64.whl", hash = "sha256:5a3ddb74b0985c4387719fc536faced33cadf2172769540c62e2a94b7b9be1c4"}, - {file = "rpds_py-0.25.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b5ffe453cde61f73fea9430223c81d29e2fbf412a6073951102146c84e19e34c"}, - {file = "rpds_py-0.25.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:115874ae5e2fdcfc16b2aedc95b5eef4aebe91b28e7e21951eda8a5dc0d3461b"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a714bf6e5e81b0e570d01f56e0c89c6375101b8463999ead3a93a5d2a4af91fa"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:35634369325906bcd01577da4c19e3b9541a15e99f31e91a02d010816b49bfda"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4cb2b3ddc16710548801c6fcc0cfcdeeff9dafbc983f77265877793f2660309"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9ceca1cf097ed77e1a51f1dbc8d174d10cb5931c188a4505ff9f3e119dfe519b"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c2cd1a4b0c2b8c5e31ffff50d09f39906fe351389ba143c195566056c13a7ea"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1de336a4b164c9188cb23f3703adb74a7623ab32d20090d0e9bf499a2203ad65"}, - {file = "rpds_py-0.25.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9fca84a15333e925dd59ce01da0ffe2ffe0d6e5d29a9eeba2148916d1824948c"}, - {file = "rpds_py-0.25.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:88ec04afe0c59fa64e2f6ea0dd9657e04fc83e38de90f6de201954b4d4eb59bd"}, - {file = "rpds_py-0.25.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a8bd2f19e312ce3e1d2c635618e8a8d8132892bb746a7cf74780a489f0f6cdcb"}, - {file = "rpds_py-0.25.1-cp312-cp312-win32.whl", hash = "sha256:e5e2f7280d8d0d3ef06f3ec1b4fd598d386cc6f0721e54f09109a8132182fbfe"}, - {file = "rpds_py-0.25.1-cp312-cp312-win_amd64.whl", hash = "sha256:db58483f71c5db67d643857404da360dce3573031586034b7d59f245144cc192"}, - {file = "rpds_py-0.25.1-cp312-cp312-win_arm64.whl", hash = "sha256:6d50841c425d16faf3206ddbba44c21aa3310a0cebc3c1cdfc3e3f4f9f6f5728"}, - {file = "rpds_py-0.25.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:659d87430a8c8c704d52d094f5ba6fa72ef13b4d385b7e542a08fc240cb4a559"}, - {file = "rpds_py-0.25.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:68f6f060f0bbdfb0245267da014d3a6da9be127fe3e8cc4a68c6f833f8a23bb1"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:083a9513a33e0b92cf6e7a6366036c6bb43ea595332c1ab5c8ae329e4bcc0a9c"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:816568614ecb22b18a010c7a12559c19f6fe993526af88e95a76d5a60b8b75fb"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c6564c0947a7f52e4792983f8e6cf9bac140438ebf81f527a21d944f2fd0a40"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c4a128527fe415d73cf1f70a9a688d06130d5810be69f3b553bf7b45e8acf79"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a49e1d7a4978ed554f095430b89ecc23f42014a50ac385eb0c4d163ce213c325"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d74ec9bc0e2feb81d3f16946b005748119c0f52a153f6db6a29e8cd68636f295"}, - {file = "rpds_py-0.25.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3af5b4cc10fa41e5bc64e5c198a1b2d2864337f8fcbb9a67e747e34002ce812b"}, - {file = "rpds_py-0.25.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:79dc317a5f1c51fd9c6a0c4f48209c6b8526d0524a6904fc1076476e79b00f98"}, - {file = "rpds_py-0.25.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1521031351865e0181bc585147624d66b3b00a84109b57fcb7a779c3ec3772cd"}, - {file = "rpds_py-0.25.1-cp313-cp313-win32.whl", hash = "sha256:5d473be2b13600b93a5675d78f59e63b51b1ba2d0476893415dfbb5477e65b31"}, - {file = "rpds_py-0.25.1-cp313-cp313-win_amd64.whl", hash = "sha256:a7b74e92a3b212390bdce1d93da9f6488c3878c1d434c5e751cbc202c5e09500"}, - {file = "rpds_py-0.25.1-cp313-cp313-win_arm64.whl", hash = "sha256:dd326a81afe332ede08eb39ab75b301d5676802cdffd3a8f287a5f0b694dc3f5"}, - {file = "rpds_py-0.25.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:a58d1ed49a94d4183483a3ce0af22f20318d4a1434acee255d683ad90bf78129"}, - {file = "rpds_py-0.25.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f251bf23deb8332823aef1da169d5d89fa84c89f67bdfb566c49dea1fccfd50d"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dbd586bfa270c1103ece2109314dd423df1fa3d9719928b5d09e4840cec0d72"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d273f136e912aa101a9274c3145dcbddbe4bac560e77e6d5b3c9f6e0ed06d34"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:666fa7b1bd0a3810a7f18f6d3a25ccd8866291fbbc3c9b912b917a6715874bb9"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:921954d7fbf3fccc7de8f717799304b14b6d9a45bbeec5a8d7408ccbf531faf5"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3d86373ff19ca0441ebeb696ef64cb58b8b5cbacffcda5a0ec2f3911732a194"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c8980cde3bb8575e7c956a530f2c217c1d6aac453474bf3ea0f9c89868b531b6"}, - {file = "rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8eb8c84ecea987a2523e057c0d950bcb3f789696c0499290b8d7b3107a719d78"}, - {file = "rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:e43a005671a9ed5a650f3bc39e4dbccd6d4326b24fb5ea8be5f3a43a6f576c72"}, - {file = "rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:58f77c60956501a4a627749a6dcb78dac522f249dd96b5c9f1c6af29bfacfb66"}, - {file = "rpds_py-0.25.1-cp313-cp313t-win32.whl", hash = "sha256:2cb9e5b5e26fc02c8a4345048cd9998c2aca7c2712bd1b36da0c72ee969a3523"}, - {file = "rpds_py-0.25.1-cp313-cp313t-win_amd64.whl", hash = "sha256:401ca1c4a20cc0510d3435d89c069fe0a9ae2ee6495135ac46bdd49ec0495763"}, - {file = "rpds_py-0.25.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:ce4c8e485a3c59593f1a6f683cf0ea5ab1c1dc94d11eea5619e4fb5228b40fbd"}, - {file = "rpds_py-0.25.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d8222acdb51a22929c3b2ddb236b69c59c72af4019d2cba961e2f9add9b6e634"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4593c4eae9b27d22df41cde518b4b9e4464d139e4322e2127daa9b5b981b76be"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd035756830c712b64725a76327ce80e82ed12ebab361d3a1cdc0f51ea21acb0"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:114a07e85f32b125404f28f2ed0ba431685151c037a26032b213c882f26eb908"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dec21e02e6cc932538b5203d3a8bd6aa1480c98c4914cb88eea064ecdbc6396a"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09eab132f41bf792c7a0ea1578e55df3f3e7f61888e340779b06050a9a3f16e9"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c98f126c4fc697b84c423e387337d5b07e4a61e9feac494362a59fd7a2d9ed80"}, - {file = "rpds_py-0.25.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0e6a327af8ebf6baba1c10fadd04964c1965d375d318f4435d5f3f9651550f4a"}, - {file = "rpds_py-0.25.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:bc120d1132cff853ff617754196d0ac0ae63befe7c8498bd67731ba368abe451"}, - {file = "rpds_py-0.25.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:140f61d9bed7839446bdd44852e30195c8e520f81329b4201ceead4d64eb3a9f"}, - {file = "rpds_py-0.25.1-cp39-cp39-win32.whl", hash = "sha256:9c006f3aadeda131b438c3092124bd196b66312f0caa5823ef09585a669cf449"}, - {file = "rpds_py-0.25.1-cp39-cp39-win_amd64.whl", hash = "sha256:a61d0b2c7c9a0ae45732a77844917b427ff16ad5464b4d4f5e4adb955f582890"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b24bf3cd93d5b6ecfbedec73b15f143596c88ee249fa98cefa9a9dc9d92c6f28"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:0eb90e94f43e5085623932b68840b6f379f26db7b5c2e6bcef3179bd83c9330f"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d50e4864498a9ab639d6d8854b25e80642bd362ff104312d9770b05d66e5fb13"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c9409b47ba0650544b0bb3c188243b83654dfe55dcc173a86832314e1a6a35d"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:796ad874c89127c91970652a4ee8b00d56368b7e00d3477f4415fe78164c8000"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:85608eb70a659bf4c1142b2781083d4b7c0c4e2c90eff11856a9754e965b2540"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4feb9211d15d9160bc85fa72fed46432cdc143eb9cf6d5ca377335a921ac37b"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ccfa689b9246c48947d31dd9d8b16d89a0ecc8e0e26ea5253068efb6c542b76e"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:3c5b317ecbd8226887994852e85de562f7177add602514d4ac40f87de3ae45a8"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:454601988aab2c6e8fd49e7634c65476b2b919647626208e376afcd22019eeb8"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:1c0c434a53714358532d13539272db75a5ed9df75a4a090a753ac7173ec14e11"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f73ce1512e04fbe2bc97836e89830d6b4314c171587a99688082d090f934d20a"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ee86d81551ec68a5c25373c5643d343150cc54672b5e9a0cafc93c1870a53954"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:89c24300cd4a8e4a51e55c31a8ff3918e6651b241ee8876a42cc2b2a078533ba"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:771c16060ff4e79584dc48902a91ba79fd93eade3aa3a12d6d2a4aadaf7d542b"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:785ffacd0ee61c3e60bdfde93baa6d7c10d86f15655bd706c89da08068dc5038"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a40046a529cc15cef88ac5ab589f83f739e2d332cb4d7399072242400ed68c9"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:85fc223d9c76cabe5d0bff82214459189720dc135db45f9f66aa7cffbf9ff6c1"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0be9965f93c222fb9b4cc254235b3b2b215796c03ef5ee64f995b1b69af0762"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8378fa4a940f3fb509c081e06cb7f7f2adae8cf46ef258b0e0ed7519facd573e"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:33358883a4490287e67a2c391dfaea4d9359860281db3292b6886bf0be3d8692"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1d1fadd539298e70cac2f2cb36f5b8a65f742b9b9f1014dd4ea1f7785e2470bf"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9a46c2fb2545e21181445515960006e85d22025bd2fe6db23e76daec6eb689fe"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:50f2c501a89c9a5f4e454b126193c5495b9fb441a75b298c60591d8a2eb92e1b"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d779b325cc8238227c47fbc53964c8cc9a941d5dbae87aa007a1f08f2f77b23"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:036ded36bedb727beeabc16dc1dad7cb154b3fa444e936a03b67a86dc6a5066e"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:245550f5a1ac98504147cba96ffec8fabc22b610742e9150138e5d60774686d7"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff7c23ba0a88cb7b104281a99476cccadf29de2a0ef5ce864959a52675b1ca83"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e37caa8cdb3b7cf24786451a0bdb853f6347b8b92005eeb64225ae1db54d1c2b"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2f48ab00181600ee266a095fe815134eb456163f7d6699f525dee471f312cf"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e5fc7484fa7dce57e25063b0ec9638ff02a908304f861d81ea49273e43838c1"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:d3c10228d6cf6fe2b63d2e7985e94f6916fa46940df46b70449e9ff9297bd3d1"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:5d9e40f32745db28c1ef7aad23f6fc458dc1e29945bd6781060f0d15628b8ddf"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:35a8d1a24b5936b35c5003313bc177403d8bdef0f8b24f28b1c4a255f94ea992"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:6099263f526efff9cf3883dfef505518730f7a7a93049b1d90d42e50a22b4793"}, - {file = "rpds_py-0.25.1.tar.gz", hash = "sha256:8960b6dac09b62dac26e75d7e2c4a22efb835d827a7278c34f72b2b84fa160e3"}, + {file = "rpds_py-0.26.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4c70c70f9169692b36307a95f3d8c0a9fcd79f7b4a383aad5eaa0e9718b79b37"}, + {file = "rpds_py-0.26.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:777c62479d12395bfb932944e61e915741e364c843afc3196b694db3d669fcd0"}, + {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec671691e72dff75817386aa02d81e708b5a7ec0dec6669ec05213ff6b77e1bd"}, + {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a1cb5d6ce81379401bbb7f6dbe3d56de537fb8235979843f0d53bc2e9815a79"}, + {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f789e32fa1fb6a7bf890e0124e7b42d1e60d28ebff57fe806719abb75f0e9a3"}, + {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c55b0a669976cf258afd718de3d9ad1b7d1fe0a91cd1ab36f38b03d4d4aeaaf"}, + {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c70d9ec912802ecfd6cd390dadb34a9578b04f9bcb8e863d0a7598ba5e9e7ccc"}, + {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3021933c2cb7def39d927b9862292e0f4c75a13d7de70eb0ab06efed4c508c19"}, + {file = "rpds_py-0.26.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8a7898b6ca3b7d6659e55cdac825a2e58c638cbf335cde41f4619e290dd0ad11"}, + {file = "rpds_py-0.26.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:12bff2ad9447188377f1b2794772f91fe68bb4bbfa5a39d7941fbebdbf8c500f"}, + {file = "rpds_py-0.26.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:191aa858f7d4902e975d4cf2f2d9243816c91e9605070aeb09c0a800d187e323"}, + {file = "rpds_py-0.26.0-cp310-cp310-win32.whl", hash = "sha256:b37a04d9f52cb76b6b78f35109b513f6519efb481d8ca4c321f6a3b9580b3f45"}, + {file = "rpds_py-0.26.0-cp310-cp310-win_amd64.whl", hash = "sha256:38721d4c9edd3eb6670437d8d5e2070063f305bfa2d5aa4278c51cedcd508a84"}, + {file = "rpds_py-0.26.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:9e8cb77286025bdb21be2941d64ac6ca016130bfdcd228739e8ab137eb4406ed"}, + {file = "rpds_py-0.26.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e09330b21d98adc8ccb2dbb9fc6cb434e8908d4c119aeaa772cb1caab5440a0"}, + {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c9c1b92b774b2e68d11193dc39620d62fd8ab33f0a3c77ecdabe19c179cdbc1"}, + {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:824e6d3503ab990d7090768e4dfd9e840837bae057f212ff9f4f05ec6d1975e7"}, + {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ad7fd2258228bf288f2331f0a6148ad0186b2e3643055ed0db30990e59817a6"}, + {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0dc23bbb3e06ec1ea72d515fb572c1fea59695aefbffb106501138762e1e915e"}, + {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d80bf832ac7b1920ee29a426cdca335f96a2b5caa839811803e999b41ba9030d"}, + {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0919f38f5542c0a87e7b4afcafab6fd2c15386632d249e9a087498571250abe3"}, + {file = "rpds_py-0.26.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d422b945683e409000c888e384546dbab9009bb92f7c0b456e217988cf316107"}, + {file = "rpds_py-0.26.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:77a7711fa562ba2da1aa757e11024ad6d93bad6ad7ede5afb9af144623e5f76a"}, + {file = "rpds_py-0.26.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:238e8c8610cb7c29460e37184f6799547f7e09e6a9bdbdab4e8edb90986a2318"}, + {file = "rpds_py-0.26.0-cp311-cp311-win32.whl", hash = "sha256:893b022bfbdf26d7bedb083efeea624e8550ca6eb98bf7fea30211ce95b9201a"}, + {file = "rpds_py-0.26.0-cp311-cp311-win_amd64.whl", hash = "sha256:87a5531de9f71aceb8af041d72fc4cab4943648d91875ed56d2e629bef6d4c03"}, + {file = "rpds_py-0.26.0-cp311-cp311-win_arm64.whl", hash = "sha256:de2713f48c1ad57f89ac25b3cb7daed2156d8e822cf0eca9b96a6f990718cc41"}, + {file = "rpds_py-0.26.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:894514d47e012e794f1350f076c427d2347ebf82f9b958d554d12819849a369d"}, + {file = "rpds_py-0.26.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc921b96fa95a097add244da36a1d9e4f3039160d1d30f1b35837bf108c21136"}, + {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e1157659470aa42a75448b6e943c895be8c70531c43cb78b9ba990778955582"}, + {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:521ccf56f45bb3a791182dc6b88ae5f8fa079dd705ee42138c76deb1238e554e"}, + {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9def736773fd56b305c0eef698be5192c77bfa30d55a0e5885f80126c4831a15"}, + {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdad4ea3b4513b475e027be79e5a0ceac8ee1c113a1a11e5edc3c30c29f964d8"}, + {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82b165b07f416bdccf5c84546a484cc8f15137ca38325403864bfdf2b5b72f6a"}, + {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d04cab0a54b9dba4d278fe955a1390da3cf71f57feb78ddc7cb67cbe0bd30323"}, + {file = "rpds_py-0.26.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:79061ba1a11b6a12743a2b0f72a46aa2758613d454aa6ba4f5a265cc48850158"}, + {file = "rpds_py-0.26.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f405c93675d8d4c5ac87364bb38d06c988e11028a64b52a47158a355079661f3"}, + {file = "rpds_py-0.26.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dafd4c44b74aa4bed4b250f1aed165b8ef5de743bcca3b88fc9619b6087093d2"}, + {file = "rpds_py-0.26.0-cp312-cp312-win32.whl", hash = "sha256:3da5852aad63fa0c6f836f3359647870e21ea96cf433eb393ffa45263a170d44"}, + {file = "rpds_py-0.26.0-cp312-cp312-win_amd64.whl", hash = "sha256:cf47cfdabc2194a669dcf7a8dbba62e37a04c5041d2125fae0233b720da6f05c"}, + {file = "rpds_py-0.26.0-cp312-cp312-win_arm64.whl", hash = "sha256:20ab1ae4fa534f73647aad289003f1104092890849e0266271351922ed5574f8"}, + {file = "rpds_py-0.26.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:696764a5be111b036256c0b18cd29783fab22154690fc698062fc1b0084b511d"}, + {file = "rpds_py-0.26.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1e6c15d2080a63aaed876e228efe4f814bc7889c63b1e112ad46fdc8b368b9e1"}, + {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:390e3170babf42462739a93321e657444f0862c6d722a291accc46f9d21ed04e"}, + {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7da84c2c74c0f5bc97d853d9e17bb83e2dcafcff0dc48286916001cc114379a1"}, + {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c5fe114a6dd480a510b6d3661d09d67d1622c4bf20660a474507aaee7eeeee9"}, + {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3100b3090269f3a7ea727b06a6080d4eb7439dca4c0e91a07c5d133bb1727ea7"}, + {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c03c9b0c64afd0320ae57de4c982801271c0c211aa2d37f3003ff5feb75bb04"}, + {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5963b72ccd199ade6ee493723d18a3f21ba7d5b957017607f815788cef50eaf1"}, + {file = "rpds_py-0.26.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9da4e873860ad5bab3291438525cae80169daecbfafe5657f7f5fb4d6b3f96b9"}, + {file = "rpds_py-0.26.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5afaddaa8e8c7f1f7b4c5c725c0070b6eed0228f705b90a1732a48e84350f4e9"}, + {file = "rpds_py-0.26.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4916dc96489616a6f9667e7526af8fa693c0fdb4f3acb0e5d9f4400eb06a47ba"}, + {file = "rpds_py-0.26.0-cp313-cp313-win32.whl", hash = "sha256:2a343f91b17097c546b93f7999976fd6c9d5900617aa848c81d794e062ab302b"}, + {file = "rpds_py-0.26.0-cp313-cp313-win_amd64.whl", hash = "sha256:0a0b60701f2300c81b2ac88a5fb893ccfa408e1c4a555a77f908a2596eb875a5"}, + {file = "rpds_py-0.26.0-cp313-cp313-win_arm64.whl", hash = "sha256:257d011919f133a4746958257f2c75238e3ff54255acd5e3e11f3ff41fd14256"}, + {file = "rpds_py-0.26.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:529c8156d7506fba5740e05da8795688f87119cce330c244519cf706a4a3d618"}, + {file = "rpds_py-0.26.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f53ec51f9d24e9638a40cabb95078ade8c99251945dad8d57bf4aabe86ecee35"}, + {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab504c4d654e4a29558eaa5bb8cea5fdc1703ea60a8099ffd9c758472cf913f"}, + {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fd0641abca296bc1a00183fe44f7fced8807ed49d501f188faa642d0e4975b83"}, + {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69b312fecc1d017b5327afa81d4da1480f51c68810963a7336d92203dbb3d4f1"}, + {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c741107203954f6fc34d3066d213d0a0c40f7bb5aafd698fb39888af277c70d8"}, + {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc3e55a7db08dc9a6ed5fb7103019d2c1a38a349ac41901f9f66d7f95750942f"}, + {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e851920caab2dbcae311fd28f4313c6953993893eb5c1bb367ec69d9a39e7ed"}, + {file = "rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:dfbf280da5f876d0b00c81f26bedce274e72a678c28845453885a9b3c22ae632"}, + {file = "rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1cc81d14ddfa53d7f3906694d35d54d9d3f850ef8e4e99ee68bc0d1e5fed9a9c"}, + {file = "rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dca83c498b4650a91efcf7b88d669b170256bf8017a5db6f3e06c2bf031f57e0"}, + {file = "rpds_py-0.26.0-cp313-cp313t-win32.whl", hash = "sha256:4d11382bcaf12f80b51d790dee295c56a159633a8e81e6323b16e55d81ae37e9"}, + {file = "rpds_py-0.26.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff110acded3c22c033e637dd8896e411c7d3a11289b2edf041f86663dbc791e9"}, + {file = "rpds_py-0.26.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:da619979df60a940cd434084355c514c25cf8eb4cf9a508510682f6c851a4f7a"}, + {file = "rpds_py-0.26.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ea89a2458a1a75f87caabefe789c87539ea4e43b40f18cff526052e35bbb4fdf"}, + {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feac1045b3327a45944e7dcbeb57530339f6b17baff154df51ef8b0da34c8c12"}, + {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b818a592bd69bfe437ee8368603d4a2d928c34cffcdf77c2e761a759ffd17d20"}, + {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a8b0dd8648709b62d9372fc00a57466f5fdeefed666afe3fea5a6c9539a0331"}, + {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d3498ad0df07d81112aa6ec6c95a7e7b1ae00929fb73e7ebee0f3faaeabad2f"}, + {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24a4146ccb15be237fdef10f331c568e1b0e505f8c8c9ed5d67759dac58ac246"}, + {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a9a63785467b2d73635957d32a4f6e73d5e4df497a16a6392fa066b753e87387"}, + {file = "rpds_py-0.26.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:de4ed93a8c91debfd5a047be327b7cc8b0cc6afe32a716bbbc4aedca9e2a83af"}, + {file = "rpds_py-0.26.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:caf51943715b12af827696ec395bfa68f090a4c1a1d2509eb4e2cb69abbbdb33"}, + {file = "rpds_py-0.26.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4a59e5bc386de021f56337f757301b337d7ab58baa40174fb150accd480bc953"}, + {file = "rpds_py-0.26.0-cp314-cp314-win32.whl", hash = "sha256:92c8db839367ef16a662478f0a2fe13e15f2227da3c1430a782ad0f6ee009ec9"}, + {file = "rpds_py-0.26.0-cp314-cp314-win_amd64.whl", hash = "sha256:b0afb8cdd034150d4d9f53926226ed27ad15b7f465e93d7468caaf5eafae0d37"}, + {file = "rpds_py-0.26.0-cp314-cp314-win_arm64.whl", hash = "sha256:ca3f059f4ba485d90c8dc75cb5ca897e15325e4e609812ce57f896607c1c0867"}, + {file = "rpds_py-0.26.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:5afea17ab3a126006dc2f293b14ffc7ef3c85336cf451564a0515ed7648033da"}, + {file = "rpds_py-0.26.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:69f0c0a3df7fd3a7eec50a00396104bb9a843ea6d45fcc31c2d5243446ffd7a7"}, + {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:801a71f70f9813e82d2513c9a96532551fce1e278ec0c64610992c49c04c2dad"}, + {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df52098cde6d5e02fa75c1f6244f07971773adb4a26625edd5c18fee906fa84d"}, + {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bc596b30f86dc6f0929499c9e574601679d0341a0108c25b9b358a042f51bca"}, + {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dfbe56b299cf5875b68eb6f0ebaadc9cac520a1989cac0db0765abfb3709c19"}, + {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac64f4b2bdb4ea622175c9ab7cf09444e412e22c0e02e906978b3b488af5fde8"}, + {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:181ef9b6bbf9845a264f9aa45c31836e9f3c1f13be565d0d010e964c661d1e2b"}, + {file = "rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:49028aa684c144ea502a8e847d23aed5e4c2ef7cadfa7d5eaafcb40864844b7a"}, + {file = "rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e5d524d68a474a9688336045bbf76cb0def88549c1b2ad9dbfec1fb7cfbe9170"}, + {file = "rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c1851f429b822831bd2edcbe0cfd12ee9ea77868f8d3daf267b189371671c80e"}, + {file = "rpds_py-0.26.0-cp314-cp314t-win32.whl", hash = "sha256:7bdb17009696214c3b66bb3590c6d62e14ac5935e53e929bcdbc5a495987a84f"}, + {file = "rpds_py-0.26.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f14440b9573a6f76b4ee4770c13f0b5921f71dde3b6fcb8dabbefd13b7fe05d7"}, + {file = "rpds_py-0.26.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:7a48af25d9b3c15684059d0d1fc0bc30e8eee5ca521030e2bffddcab5be40226"}, + {file = "rpds_py-0.26.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0c71c2f6bf36e61ee5c47b2b9b5d47e4d1baad6426bfed9eea3e858fc6ee8806"}, + {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d815d48b1804ed7867b539236b6dd62997850ca1c91cad187f2ddb1b7bbef19"}, + {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84cfbd4d4d2cdeb2be61a057a258d26b22877266dd905809e94172dff01a42ae"}, + {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fbaa70553ca116c77717f513e08815aec458e6b69a028d4028d403b3bc84ff37"}, + {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39bfea47c375f379d8e87ab4bb9eb2c836e4f2069f0f65731d85e55d74666387"}, + {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1533b7eb683fb5f38c1d68a3c78f5fdd8f1412fa6b9bf03b40f450785a0ab915"}, + {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c5ab0ee51f560d179b057555b4f601b7df909ed31312d301b99f8b9fc6028284"}, + {file = "rpds_py-0.26.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e5162afc9e0d1f9cae3b577d9c29ddbab3505ab39012cb794d94a005825bde21"}, + {file = "rpds_py-0.26.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:43f10b007033f359bc3fa9cd5e6c1e76723f056ffa9a6b5c117cc35720a80292"}, + {file = "rpds_py-0.26.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e3730a48e5622e598293eee0762b09cff34dd3f271530f47b0894891281f051d"}, + {file = "rpds_py-0.26.0-cp39-cp39-win32.whl", hash = "sha256:4b1f66eb81eab2e0ff5775a3a312e5e2e16bf758f7b06be82fb0d04078c7ac51"}, + {file = "rpds_py-0.26.0-cp39-cp39-win_amd64.whl", hash = "sha256:519067e29f67b5c90e64fb1a6b6e9d2ec0ba28705c51956637bac23a2f4ddae1"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3c0909c5234543ada2515c05dc08595b08d621ba919629e94427e8e03539c958"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:c1fb0cda2abcc0ac62f64e2ea4b4e64c57dfd6b885e693095460c61bde7bb18e"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84d142d2d6cf9b31c12aa4878d82ed3b2324226270b89b676ac62ccd7df52d08"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a547e21c5610b7e9093d870be50682a6a6cf180d6da0f42c47c306073bfdbbf6"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:35e9a70a0f335371275cdcd08bc5b8051ac494dd58bff3bbfb421038220dc871"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0dfa6115c6def37905344d56fb54c03afc49104e2ca473d5dedec0f6606913b4"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:313cfcd6af1a55a286a3c9a25f64af6d0e46cf60bc5798f1db152d97a216ff6f"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f7bf2496fa563c046d05e4d232d7b7fd61346e2402052064b773e5c378bf6f73"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:aa81873e2c8c5aa616ab8e017a481a96742fdf9313c40f14338ca7dbf50cb55f"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:68ffcf982715f5b5b7686bdd349ff75d422e8f22551000c24b30eaa1b7f7ae84"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6188de70e190847bb6db3dc3981cbadff87d27d6fe9b4f0e18726d55795cee9b"}, + {file = "rpds_py-0.26.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1c962145c7473723df9722ba4c058de12eb5ebedcb4e27e7d902920aa3831ee8"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f61a9326f80ca59214d1cceb0a09bb2ece5b2563d4e0cd37bfd5515c28510674"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:183f857a53bcf4b1b42ef0f57ca553ab56bdd170e49d8091e96c51c3d69ca696"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:941c1cfdf4799d623cf3aa1d326a6b4fdb7a5799ee2687f3516738216d2262fb"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72a8d9564a717ee291f554eeb4bfeafe2309d5ec0aa6c475170bdab0f9ee8e88"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:511d15193cbe013619dd05414c35a7dedf2088fcee93c6bbb7c77859765bd4e8"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aea1f9741b603a8d8fedb0ed5502c2bc0accbc51f43e2ad1337fe7259c2b77a5"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4019a9d473c708cf2f16415688ef0b4639e07abaa569d72f74745bbeffafa2c7"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:093d63b4b0f52d98ebae33b8c50900d3d67e0666094b1be7a12fffd7f65de74b"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2abe21d8ba64cded53a2a677e149ceb76dcf44284202d737178afe7ba540c1eb"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:4feb7511c29f8442cbbc28149a92093d32e815a28aa2c50d333826ad2a20fdf0"}, + {file = "rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e99685fc95d386da368013e7fb4269dd39c30d99f812a8372d62f244f662709c"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a90a13408a7a856b87be8a9f008fff53c5080eea4e4180f6c2e546e4a972fb5d"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3ac51b65e8dc76cf4949419c54c5528adb24fc721df722fd452e5fbc236f5c40"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59b2093224a18c6508d95cfdeba8db9cbfd6f3494e94793b58972933fcee4c6d"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4f01a5d6444a3258b00dc07b6ea4733e26f8072b788bef750baa37b370266137"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6e2c12160c72aeda9d1283e612f68804621f448145a210f1bf1d79151c47090"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cb28c1f569f8d33b2b5dcd05d0e6ef7005d8639c54c2f0be824f05aedf715255"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1766b5724c3f779317d5321664a343c07773c8c5fd1532e4039e6cc7d1a815be"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b6d9e5a2ed9c4988c8f9b28b3bc0e3e5b1aaa10c28d210a594ff3a8c02742daf"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:b5f7a446ddaf6ca0fad9a5535b56fbfc29998bf0e0b450d174bbec0d600e1d72"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:eed5ac260dd545fbc20da5f4f15e7efe36a55e0e7cf706e4ec005b491a9546a0"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:582462833ba7cee52e968b0341b85e392ae53d44c0f9af6a5927c80e539a8b67"}, + {file = "rpds_py-0.26.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:69a607203441e07e9a8a529cff1d5b73f6a160f22db1097211e6212a68567d11"}, + {file = "rpds_py-0.26.0.tar.gz", hash = "sha256:20dae58a859b0906f0685642e591056f1e787f3a8b39c8e8749a45dc7d26bdb0"}, ] [[package]] @@ -5183,4 +5163,4 @@ worker = ["celery", "celery-prometheus-exporter", "django-celery-beat", "django- [metadata] lock-version = "2.0" python-versions = ">=3.12,<3.13" -content-hash = "659721d93224050ebe572b017a80d45826b288764427c24bd07fbd35b704fa48" +content-hash = "58d67f7b6c2313bdb117965a9c9555319bbb059db043e5723d39a27c36695939" diff --git a/pyproject.toml b/pyproject.toml index 0ed53114..c84498a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "eVibes" -version = "2.8.10" +version = "2.9.2" description = "eVibes is an open-source eCommerce backend service built with Django. It’s designed for flexibility, making it ideal for various use cases and learning Django skills. The project is easy to customize, allowing for straightforward editing and extension." authors = ["fureunoir "] readme = "README.md" @@ -19,7 +19,6 @@ django-celery-beat = { version = "2.8.1", optional = true } django-celery-results = { version = "2.6.0", optional = true } django-constance = "4.3.2" django-cors-headers = "4.7.0" -django-daisy = "1.0.26" django-dbbackup = "4.3.0" django-elasticsearch-dsl = "8.0" django-elasticsearch-dsl-drf = "0.22.5" @@ -27,6 +26,7 @@ django-extensions = "4.1" django-filter = "25.1" django-health-check = "3.20.0" django-hosts = "6.0" +django-jazzmin = "3.0.1" django-json-widget = "2.0.1" django-mailbox = "4.10.1" django-model-utils = "5.0.0" @@ -47,6 +47,7 @@ djangorestframework-simplejwt = { extras = ["crypto"], version = "5.5.0" } djangorestframework-stubs = "3.16.0" djangorestframework-xml = "2.0.0" djangorestframework-yaml = "2.0.0" +docutils = "0.21.2" drf-spectacular = { extras = ["sidecar"], version = "0.28.0" } elasticsearch = "8.18.1" elasticsearch-dsl = "8.18.0" @@ -102,22 +103,22 @@ testing = ["pytest", "pytest-django", "coverage"] linting = ["black", "isort", "flake8", "bandit"] [tool.mypy] -disable_error_code = ["import-untyped", "misc"] -exclude = ["*/migrations/*", "./evibes/settings/drf.py"] +disable_error_code = ["no-redef", "import-untyped"] +exclude = ["*/migrations/*", "storefront/*"] +plugins = ["mypy_django_plugin.main", "mypy_drf_plugin.main"] + +[tool.django-stubs] +django_settings_module = "evibes.settings" [tool.ruff] line-length = 120 target-version = "py312" -exclude = ["migrations", "media", "static", "storefront"] +exclude = ["media", "static", "storefront"] [tool.ruff.lint] -select = ["E", "W", "F", "B", "I", "RUF", "UP", "N", "A", "COM", "C4", "DJ001", "RSE", "SIM", "ISC", "TID252", "PGH004"] -ignore = ["B904", "RUF001", "RUF002", "RUF003", "RUF005", "RUF012", "A003", "A002", "COM812", "S603"] -per-file-ignores = { "__init__.py" = ["E402", "F401"] } +select = ["E4", "E7", "E9", "F", "B", "Q"] +ignore = ["RUF012", "A002", "A003"] [tool.ruff.format] quote-style = "double" -indent-style = "space" - -[tool.yapf] -based_on_style = "pep8" \ No newline at end of file +indent-style = "space" \ No newline at end of file diff --git a/scripts/Docker/app-entrypoint.sh b/scripts/Docker/app-entrypoint.sh index 73fb6d95..05ddd61e 100644 --- a/scripts/Docker/app-entrypoint.sh +++ b/scripts/Docker/app-entrypoint.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/usr/bin/bash set -e # wait for auxiliary services @@ -18,4 +18,4 @@ else --bind 0.0.0.0:8000 \ --workers 12 \ --timeout 120 -fi \ No newline at end of file +fi diff --git a/scripts/Docker/beat-entrypoint.sh b/scripts/Docker/beat-entrypoint.sh index f0db32d5..d1779697 100644 --- a/scripts/Docker/beat-entrypoint.sh +++ b/scripts/Docker/beat-entrypoint.sh @@ -1,8 +1,8 @@ -#!/usr/bin/env sh +#!/usr/bin/bash set -e # wait for auxiliary services poetry run python manage.py await_services # run beat -poetry run celery -A evibes beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler \ No newline at end of file +poetry run celery -A evibes beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler diff --git a/scripts/Docker/stock-updater-entrypoint.sh b/scripts/Docker/stock-updater-entrypoint.sh new file mode 100644 index 00000000..1686cd32 --- /dev/null +++ b/scripts/Docker/stock-updater-entrypoint.sh @@ -0,0 +1,8 @@ +#!/usr/bin/bash +set -e + +# wait for auxiliary services +poetry run python manage.py await_services + +# run stock_updater +poetry run celery -A evibes worker --pool=prefork --concurrency=1 --queues=stock_updater --loglevel=info --max-tasks-per-child=1 diff --git a/scripts/Docker/worker-entrypoint.sh b/scripts/Docker/worker-entrypoint.sh index 9c81ffdc..f811766f 100644 --- a/scripts/Docker/worker-entrypoint.sh +++ b/scripts/Docker/worker-entrypoint.sh @@ -1,8 +1,8 @@ -#!/usr/bin/env sh +#!/usr/bin/bash set -e # wait for auxiliary services poetry run python manage.py await_services -# run workers and metrics exporter -poetry run celery -A evibes worker --loglevel=info -E --concurrency=4 --autoscale=4,2 --max-tasks-per-child=100 --max-memory-per-child=512000 --soft-time-limit=10800 --time-limit=21600 & /usr/local/bin/celery-prometheus-exporter \ No newline at end of file +# run worker and metrics exporter +poetry run celery -A evibes worker --pool=prefork --concurrency=8 --loglevel=info -E --queues=default --prefetch-multiplier=1 --max-tasks-per-child=100 --max-memory-per-child=512000 --soft-time-limit=3600 --time-limit=7200 & /usr/local/bin/celery-prometheus-exporter diff --git a/scripts/Unix/generate-environment-file.sh b/scripts/Unix/generate-environment-file.sh index dfa3618d..47703cdf 100755 --- a/scripts/Unix/generate-environment-file.sh +++ b/scripts/Unix/generate-environment-file.sh @@ -38,6 +38,7 @@ FRONTEND_DOMAIN=$(prompt_default EVIBES_FRONTEND_DOMAIN evibes.com) BASE_DOMAIN=$(prompt_default EVIBES_BASE_DOMAIN evibes.com) SENTRY_DSN=$(prompt_default SENTRY_DSN "") DEBUG=$(prompt_default DEBUG 1) +TIME_ZONE=$(prompt_default TIME_ZONE "Europe/London") SECRET_KEY=$(prompt_autogen SECRET_KEY 32) JWT_SIGNING_KEY=$(prompt_autogen JWT_SIGNING_KEY 64) @@ -50,9 +51,10 @@ POSTGRES_DB=$(prompt_default POSTGRES_DB evibes) POSTGRES_USER=$(prompt_default POSTGRES_USER evibes_user) POSTGRES_PASSWORD=$(prompt_autogen POSTGRES_PASSWORD 16) -DBBACKUP_SFTP_HOST=$(prompt_default DBBACKUP_SFTP_HOST "Your SFTP backup host") -DBBACKUP_SFTP_USER=$(prompt_default DBBACKUP_SFTP_USER "The username to use to log in to that host") -DBBACKUP_SFTP_PASS=$(prompt_default DBBACKUP_SFTP_PASS "The password to use to log in to that host") +DBBACKUP_TYPE=$(prompt_default DBBACKUP_TYPE "Your backup connection type") +DBBACKUP_HOST=$(prompt_default DBBACKUP_HOST "Your SFTP backup host") +DBBACKUP_USER=$(prompt_default DBBACKUP_USER "The username to use to log in to that host") +DBBACKUP_PASS=$(prompt_default DBBACKUP_PASS "The password to use to log in to that host") ELASTIC_PASSWORD=$(prompt_autogen ELASTIC_PASSWORD 16) REDIS_PASSWORD=$(prompt_autogen REDIS_PASSWORD 16) diff --git a/scripts/Unix/reboot.sh b/scripts/Unix/reboot.sh index 7f855a12..ea45fd1f 100755 --- a/scripts/Unix/reboot.sh +++ b/scripts/Unix/reboot.sh @@ -16,7 +16,7 @@ docker compose exec app poetry run python manage.py migrate --no-input --verbosi echo "Migrations applied successfully!" echo "Collecting static files..." -docker compose exec app poetry run python manage.py collectstatic --no-input --verbosity 0 +docker compose exec app poetry run python manage.py collectstatic --clear --no-input --verbosity 0 echo "Static files collected successfully!" echo "Setting default caches..." diff --git a/scripts/Unix/run.sh b/scripts/Unix/run.sh index 99c9507f..efdd2882 100755 --- a/scripts/Unix/run.sh +++ b/scripts/Unix/run.sh @@ -22,7 +22,7 @@ docker compose exec app poetry run python manage.py migrate --no-input echo "Migrations applied successfully!" echo "Collecting static files…" -docker compose exec app poetry run python manage.py collectstatic --no-input +docker compose exec app poetry run python manage.py collectstatic --clear --no-input echo "Static files collected successfully!" echo "Setting default caches…" diff --git a/scripts/Windows/backup.ps1 b/scripts/Windows/backup.ps1 index cc12a11b..bf890dd7 100644 --- a/scripts/Windows/backup.ps1 +++ b/scripts/Windows/backup.ps1 @@ -3,11 +3,20 @@ Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' .\scripts\Windows\starter.ps1 +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Starting database backup process..." -ForegroundColor Magenta docker compose exec app poetry run python manage.py dbbackup +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Database backup created under ./dbbackup" -ForegroundColor Green Write-Host "Starting media backup process..." -ForegroundColor Magenta docker compose exec app poetry run python manage.py mediabackup +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Media backup created under ./dbbackup" -ForegroundColor Green \ No newline at end of file diff --git a/scripts/Windows/compile-messages.ps1 b/scripts/Windows/compile-messages.ps1 new file mode 100644 index 00000000..c80b9c9a --- /dev/null +++ b/scripts/Windows/compile-messages.ps1 @@ -0,0 +1,27 @@ +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +.\scripts\Windows\starter.ps1 +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} + +if (-not (Test-Path '.env')) +{ + Write-Warning ".env file not found. Exiting without running Docker steps." + exit 0 +} + +Write-Host "Checking placeholders in PO files..." -ForegroundColor Magenta +docker compose exec app poetry run python manage.py check_translated -l en-GB -l ar-AR -l cs-CZ -l da-DK -l de-DE -l en-US -l es-ES -l fr-FR -l hi-IN -l it-IT -l ja-JP -l kk-KZ -l nl-NL -l pl-PL -l pt-BR -l ro-RO -l ru-RU -l zh-hans -a core -a geo -a payments -a vibes_auth -a blog -a root +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} +Write-Host "PO files have no placeholder issues!" -ForegroundColor Green + +Write-Host "Compiling PO files into MO files..." -ForegroundColor Magenta +docker compose exec app poetry run python manage.py compilemessages -l en_GB -l ar_AR -l cs_CZ -l da_DK -l de_DE -l en_US -l es_ES -l fr_FR -l hi_IN -l it_IT -l ja_JP -l kk_KZ -l nl_NL -l pl_PL -l pt_BR -l ro_RO -l ru_RU -l zh_Hans +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} +Write-Host "Compiled successfully!" -ForegroundColor Green diff --git a/scripts/Windows/export-environment-file.ps1 b/scripts/Windows/export-environment-file.ps1 index 010d44b0..402cba9e 100644 --- a/scripts/Windows/export-environment-file.ps1 +++ b/scripts/Windows/export-environment-file.ps1 @@ -3,6 +3,9 @@ Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' .\scripts\Windows\starter.ps1 +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} $envFile = '.env' diff --git a/scripts/Windows/generate-environment-file.ps1 b/scripts/Windows/generate-environment-file.ps1 index 62c1410a..7499cffd 100644 --- a/scripts/Windows/generate-environment-file.ps1 +++ b/scripts/Windows/generate-environment-file.ps1 @@ -2,6 +2,9 @@ Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' .\scripts\Windows\starter.ps1 +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} function Get-RandomHex { @@ -46,55 +49,57 @@ if (Test-Path '.env') Read-Host "Press Enter to continue or Ctrl+C to abort" } -$PROJECT_NAME = Prompt-Default 'EVIBES_PROJECT_NAME' 'eVibes' -$FRONTEND_DOMAIN = Prompt-Default 'EVIBES_FRONTEND_DOMAIN' 'evibes.com' -$BASE_DOMAIN = Prompt-Default 'EVIBES_BASE_DOMAIN' 'evibes.com' -$SENTRY_DSN = Prompt-Default 'SENTRY_DSN' '' -$DEBUG = Prompt-Default 'DEBUG' '1' +$EVIBES_PROJECT_NAME = Prompt-Default 'EVIBES_PROJECT_NAME' 'eVibes' +$EVIBES_FRONTEND_DOMAIN = Prompt-Default 'EVIBES_FRONTEND_DOMAIN' 'evibes.com' +$EVIBES_BASE_DOMAIN = Prompt-Default 'EVIBES_BASE_DOMAIN' 'evibes.com' +$SENTRY_DSN = Prompt-Default 'SENTRY_DSN' '' +$DEBUG = Prompt-Default 'DEBUG' '1' +$TIME_ZONE = Prompt-Default 'TIME_ZONE' 'Europe/London' -$SECRET_KEY = Prompt-AutoGen 'SECRET_KEY' 32 -$JWT_SIGNING_KEY = Prompt-AutoGen 'JWT_SIGNING_KEY' 64 +$SECRET_KEY = Prompt-AutoGen 'SECRET_KEY' 32 +$JWT_SIGNING_KEY = Prompt-AutoGen 'JWT_SIGNING_KEY' 64 -$ALLOWED_HOSTS = Prompt-Default 'ALLOWED_HOSTS' 'evibes.com api.evibes.com b2b.evibes.com' +$ALLOWED_HOSTS = Prompt-Default 'ALLOWED_HOSTS' 'evibes.com api.evibes.com b2b.evibes.com' $CSRF_TRUSTED_ORIGINS = Prompt-Default 'CSRF_TRUSTED_ORIGINS' 'https://evibes.com https://api.evibes.com https://www.evibes.com https://b2b.evibes.com' $CORS_ALLOWED_ORIGINS = Prompt-Default 'CORS_ALLOWED_ORIGINS' $CSRF_TRUSTED_ORIGINS -$POSTGRES_DB = Prompt-Default 'POSTGRES_DB' 'evibes' -$POSTGRES_USER = Prompt-Default 'POSTGRES_USER' 'evibes_user' -$POSTGRES_PASSWORD = Prompt-AutoGen 'POSTGRES_PASSWORD' 16 +$POSTGRES_DB = Prompt-Default 'POSTGRES_DB' 'evibes' +$POSTGRES_USER = Prompt-Default 'POSTGRES_USER' 'evibes_user' +$POSTGRES_PASSWORD = Prompt-AutoGen 'POSTGRES_PASSWORD' 16 -$DBBACKUP_SFTP_HOST = Prompt-Default 'DBBACKUP_SFTP_HOST' 'Your SFTP backup host' -$DBBACKUP_SFTP_USER = Prompt-Default 'DBBACKUP_SFTP_USER' 'The username to use to log in to that host' -$DBBACKUP_SFTP_PASS = Prompt-Default 'DBBACKUP_SFTP_PASS' 'The password to use to log in to that host' +$DBBACKUP_TYPE = Prompt-Default 'DBBACKUP_TYPE' 'Your backup connection type' +$DBBACKUP_HOST = Prompt-Default 'DBBACKUP_HOST' 'Your SFTP backup host' +$DBBACKUP_USER = Prompt-Default 'DBBACKUP_USER' 'The username to use to log in to that host' +$DBBACKUP_PASS = Prompt-Default 'DBBACKUP_PASS' 'The password to use to log in to that host' -$ELASTIC_PASSWORD = Prompt-AutoGen 'ELASTIC_PASSWORD' 16 +$ELASTIC_PASSWORD = Prompt-AutoGen 'ELASTIC_PASSWORD' 16 -$REDIS_PASSWORD = Prompt-AutoGen 'REDIS_PASSWORD' 16 +$REDIS_PASSWORD = Prompt-AutoGen 'REDIS_PASSWORD' 16 -$PROMETHEUS_USER = Prompt-Default 'PROMETHEUS_USER' 'evibes' +$PROMETHEUS_USER = Prompt-Default 'PROMETHEUS_USER' 'evibes' $PROMETHEUS_PASSWORD = Prompt-AutoGen 'PROMETHEUS_PASSWORD' 16 -$EMAIL_BACKEND = Prompt-Default 'EMAIL_BACKEND' 'django.core.mail.backends.smtp.EmailBackend' -$EMAIL_HOST = Prompt-Default 'EMAIL_HOST' 'smtp.whatever.evibes.com' -$EMAIL_PORT = Prompt-Default 'EMAIL_PORT' '465' -$EMAIL_USE_TLS = Prompt-Default 'EMAIL_USE_TLS' '0' -$EMAIL_USE_SSL = Prompt-Default 'EMAIL_USE_SSL' '1' -$EMAIL_HOST_USER = Prompt-Default 'EMAIL_HOST_USER' 'your-email-user@whatever.evibes.com' -$EMAIL_FROM = Prompt-Default 'EMAIL_FROM' $EMAIL_HOST_USER +$EMAIL_BACKEND = Prompt-Default 'EMAIL_BACKEND' 'django.core.mail.backends.smtp.EmailBackend' +$EMAIL_HOST = Prompt-Default 'EMAIL_HOST' 'smtp.whatever.evibes.com' +$EMAIL_PORT = Prompt-Default 'EMAIL_PORT' '465' +$EMAIL_USE_TLS = Prompt-Default 'EMAIL_USE_TLS' '0' +$EMAIL_USE_SSL = Prompt-Default 'EMAIL_USE_SSL' '1' +$EMAIL_HOST_USER = Prompt-Default 'EMAIL_HOST_USER' 'your-email-user@whatever.evibes.com' +$EMAIL_FROM = Prompt-Default 'EMAIL_FROM' $EMAIL_HOST_USER $EMAIL_HOST_PASSWORD = Prompt-Default 'EMAIL_HOST_PASSWORD' 'SUPERSECRETEMAILHOSTPASSWORD' -$COMPANY_NAME = Prompt-Default 'COMPANY_NAME' 'eVibes, Inc.' -$COMPANY_PHONE_NUMBER = Prompt-Default 'COMPANY_PHONE_NUMBER' '+888888888888' -$COMPANY_ADDRESS = Prompt-Default 'COMPANY_ADDRESS' 'The place that does not exist' +$COMPANY_NAME = Prompt-Default 'COMPANY_NAME' 'eVibes, Inc.' +$COMPANY_PHONE_NUMBER = Prompt-Default 'COMPANY_PHONE_NUMBER' '+888888888888' +$COMPANY_ADDRESS = Prompt-Default 'COMPANY_ADDRESS' 'The place that does not exist' -$OPENAI_API_KEY = Prompt-Default 'OPENAI_API_KEY' 'Haha, really?' -$ABSTRACT_API_KEY = Prompt-Default 'ABSTRACT_API_KEY' 'Haha, really? x2' -$DEEPL_AUTH_KEY = Prompt-Default 'DEEPL_AUTH_KEY' 'Haha, really? x3' +$OPENAI_API_KEY = Prompt-Default 'OPENAI_API_KEY' 'Haha, really?' +$ABSTRACT_API_KEY = Prompt-Default 'ABSTRACT_API_KEY' 'Haha, really? x2' +$DEEPL_AUTH_KEY = Prompt-Default 'DEEPL_AUTH_KEY' 'Haha, really? x3' $lines = @( - "EVIBES_PROJECT_NAME=""$PROJECT_NAME""" - "EVIBES_FRONTEND_DOMAIN=""$FRONTEND_DOMAIN""" - "EVIBES_BASE_DOMAIN=""$BASE_DOMAIN""" + "EVIBES_PROJECT_NAME=""$EVIBES_PROJECT_NAME""" + "EVIBES_FRONTEND_DOMAIN=""$EVIBES_FRONTEND_DOMAIN""" + "EVIBES_BASE_DOMAIN=""$EVIBES_BASE_DOMAIN""" "SENTRY_DSN=""$SENTRY_DSN""" "DEBUG=$DEBUG" "" @@ -109,9 +114,10 @@ $lines = @( "POSTGRES_USER=""$POSTGRES_USER""" "POSTGRES_PASSWORD=""$POSTGRES_PASSWORD""" "" - "DBBACKUP_SFTP_HOST=""$DBBACKUP_SFTP_HOST""" - "DBBACKUP_SFTP_USER=""$DBBACKUP_SFTP_USER""" - "DBBACKUP_SFTP_PASS=""$DBBACKUP_SFTP_PASS""" + "DBBACKUP_TYPE=""$DBBACKUP_TYPE""" + "DBBACKUP_HOST=""$DBBACKUP_HOST""" + "DBBACKUP_USER=""$DBBACKUP_USER""" + "DBBACKUP_PASS=""$DBBACKUP_PASS""" "" "ELASTIC_PASSWORD=""$ELASTIC_PASSWORD""" "" diff --git a/scripts/Windows/install.ps1 b/scripts/Windows/install.ps1 index c0d49dca..0df9aec8 100644 --- a/scripts/Windows/install.ps1 +++ b/scripts/Windows/install.ps1 @@ -2,6 +2,9 @@ Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' .\scripts\Windows\starter.ps1 +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} if (-not (Test-Path '.env')) { diff --git a/scripts/Windows/make-messages.ps1 b/scripts/Windows/make-messages.ps1 new file mode 100644 index 00000000..c7ca8997 --- /dev/null +++ b/scripts/Windows/make-messages.ps1 @@ -0,0 +1,44 @@ +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +.\scripts\Windows\starter.ps1 +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} + +if (-not (Test-Path '.env')) +{ + Write-Warning ".env file not found. Exiting without running Docker steps." + exit 0 +} + +Write-Host "Remove old fuzzy entries..." -ForegroundColor Magenta +docker compose exec app poetry run python manage.py fix_fuzzy +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} +Write-Host "Old fuzzy entries removed successfully!" -ForegroundColor Green + +Write-Host "Updating PO files..." -ForegroundColor Magenta +docker compose exec app poetry run python manage.py makemessages -l en_GB -l ar_AR -l cs_CZ -l da_DK -l de_DE -l en_US -l es_ES -l fr_FR -l hi_IN -l it_IT -l ja_JP -l kk_KZ -l nl_NL -l pl_PL -l pt_BR -l ro_RO -l ru_RU -l zh_Hans +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} +Write-Host "PO files updated successfully!" -ForegroundColor Green + +Write-Host "Fixing new fuzzy entries..." -ForegroundColor Magenta +docker compose exec app poetry run python manage.py fix_fuzzy +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} +Write-Host "New fuzzy entries fixed successfully!" -ForegroundColor Green + +Write-Host "Translating with DeepL..." -ForegroundColor Magenta +docker compose exec app poetry run python manage.py deepl_translate -l en-gb -l ar-ar -l cs-cz -l da-dk -l de-de -l en-us -l es-es -l fr-fr -l hi-in -l it-it -l ja-jp -l kk-kz -l nl-nl -l pl-pl -l pt-br -l ro-ro -l ru-ru -l zh-hans -a core -a geo -a payments -a vibes_auth -a blog -a root +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} +Write-Host "Translated successfully!" -ForegroundColor Green + +Write-Host "" +Write-Host "You can now use compile-messages.ps1 script." -ForegroundColor Cyan diff --git a/scripts/Windows/reboot.ps1 b/scripts/Windows/reboot.ps1 index a6f48430..ec0e2f2c 100644 --- a/scripts/Windows/reboot.ps1 +++ b/scripts/Windows/reboot.ps1 @@ -2,30 +2,51 @@ Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' .\scripts\Windows\starter.ps1 +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Shutting down..." -ForegroundColor Magenta docker compose down +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Services were shut down successfully!" -ForegroundColor Green Write-Host "Spinning services up..." -ForegroundColor Magenta docker compose up -d --build --wait +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Services are up and healthy!" -ForegroundColor Green Write-Host "Applying migrations..." -ForegroundColor Magenta docker compose exec app poetry run python manage.py migrate --no-input --verbosity 0 +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Migrations applied successfully!" -ForegroundColor Green Write-Host "Collecting static files..." -ForegroundColor Magenta -docker compose exec app poetry run python manage.py collectstatic --no-input --verbosity 0 +docker compose exec app poetry run python manage.py collectstatic --clear --no-input --verbosity 0 +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Static files collected successfully!" -ForegroundColor Green Write-Host "Setting default caches..." -ForegroundColor Magenta docker compose exec app poetry run python manage.py set_default_caches +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Default caches set successfully!" -ForegroundColor Green Write-Host "Cleaning up unused Docker data..." -ForegroundColor Magenta docker system prune -f +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Unused Docker data cleaned successfully!" -ForegroundColor Green Write-Host "All done! eVibes is up and running!" -ForegroundColor Cyan diff --git a/scripts/Windows/run.ps1 b/scripts/Windows/run.ps1 index e43b7a9c..38f756aa 100644 --- a/scripts/Windows/run.ps1 +++ b/scripts/Windows/run.ps1 @@ -2,6 +2,9 @@ Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' .\scripts\Windows\starter.ps1 +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Verifying all images are present…" -ForegroundColor Green @@ -29,22 +32,37 @@ foreach ($prop in $config.services.PSObject.Properties) Write-Host "Spinning services up..." -ForegroundColor Magenta docker compose up --no-build --detach --wait +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Services are up and healthy!" -ForegroundColor Green Write-Host "Applying migrations..." -ForegroundColor Magenta docker compose exec app poetry run python manage.py migrate --no-input +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Migrations applied successfully!" -ForegroundColor Green Write-Host "Collecting static files..." -ForegroundColor Magenta -docker compose exec app poetry run python manage.py collectstatic --no-input +docker compose exec app poetry run python manage.py collectstatic --clear --no-input +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Static files collected successfully!" -ForegroundColor Green Write-Host "Setting default caches..." -ForegroundColor Magenta docker compose exec app poetry run python manage.py set_default_caches +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Default caches set successfully!" -ForegroundColor Green Write-Host "Cleaning unused Docker data..." -ForegroundColor Magenta docker system prune -f +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Unused Docker data cleaned successfully!" -ForegroundColor Green Write-Host "All done! eVibes is up and running!" -ForegroundColor Cyan diff --git a/scripts/Windows/starter.ps1 b/scripts/Windows/starter.ps1 index dc4914f5..7a847b58 100644 --- a/scripts/Windows/starter.ps1 +++ b/scripts/Windows/starter.ps1 @@ -18,4 +18,5 @@ if (-not (Test-Path $artPath)) } Get-Content -Raw -Path $artPath | ForEach-Object { Write-Host "$purple$_$reset" } -Write-Host "`n by WISELESS TEAM`n" -ForegroundColor Gray \ No newline at end of file +Write-Host "`n by WISELESS TEAM`n" -ForegroundColor Gray +exit 0 \ No newline at end of file diff --git a/scripts/Windows/uninstall.ps1 b/scripts/Windows/uninstall.ps1 index bee7d3a4..2ef36b9f 100644 --- a/scripts/Windows/uninstall.ps1 +++ b/scripts/Windows/uninstall.ps1 @@ -2,18 +2,33 @@ Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' .\scripts\Windows\starter.ps1 +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Shutting down..." -ForegroundColor Magenta docker compose down +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Services were shut down successfully!" -ForegroundColor Green Write-Host "Removing volumes..." -ForegroundColor Magenta docker volume remove -f evibes_prometheus-data +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} docker volume remove -f evibes_es-data +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Volumes were removed successfully!" -ForegroundColor Green Write-Host "Cleaning up unused Docker data..." -ForegroundColor Magenta docker system prune -a -f --volumes +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} Write-Host "Unused Docker data cleaned successfully!" -ForegroundColor Green Write-Host "Removing related files..." -ForegroundColor Magenta diff --git a/storefront/.gitkeep b/storefront/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/vibes_auth/admin.py b/vibes_auth/admin.py index 3c1fc286..7dc34ba1 100644 --- a/vibes_auth/admin.py +++ b/vibes_auth/admin.py @@ -22,7 +22,7 @@ from rest_framework_simplejwt.token_blacklist.models import ( OutstandingToken as BaseOutstandingToken, ) -from core.admin import BasicModelAdmin +from core.admin import ActivationActionsMixin from core.models import Order from payments.models import Balance from vibes_auth.forms import UserForm @@ -48,7 +48,7 @@ class OrderInline(admin.TabularInline): icon = "fa-solid fa-cart-shopping" -class UserAdmin(BaseUserAdmin, BasicModelAdmin): +class UserAdmin(ActivationActionsMixin, BaseUserAdmin): # type: ignore [misc] inlines = (BalanceInline, OrderInline) fieldsets = ( (None, {"fields": ("email", "password")}), @@ -110,15 +110,15 @@ class UserAdmin(BaseUserAdmin, BasicModelAdmin): super().save_model(request, obj, form, change) -class GroupAdmin(BaseGroupAdmin, BasicModelAdmin): +class GroupAdmin(BaseGroupAdmin): pass -class BlacklistedTokenAdmin(BaseBlacklistedTokenAdmin, BasicModelAdmin): +class BlacklistedTokenAdmin(BaseBlacklistedTokenAdmin): pass -class OutstandingTokenAdmin(BaseOutstandingTokenAdmin, BasicModelAdmin): +class OutstandingTokenAdmin(BaseOutstandingTokenAdmin): pass diff --git a/vibes_auth/graphene/mutations.py b/vibes_auth/graphene/mutations.py index 9c7fe76a..c72d7379 100644 --- a/vibes_auth/graphene/mutations.py +++ b/vibes_auth/graphene/mutations.py @@ -25,7 +25,7 @@ from vibes_auth.serializers import ( from vibes_auth.utils.emailing import send_reset_password_email_task from vibes_auth.validators import is_valid_email, is_valid_phone_number -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") class CreateUser(BaseMutation): @@ -102,9 +102,9 @@ class UpdateUser(BaseMutation): try: user = User.objects.get(uuid=uuid) - except User.DoesNotExist: + except User.DoesNotExist as dne: name = "User" - raise Http404(_(f"{name} does not exist: {uuid}")) + raise Http404(_(f"{name} does not exist: {uuid}")) from dne if not (info.context.user.has_perm("vibes_auth.change_user") or info.context.user == user): raise PermissionDenied(permission_denied_message) @@ -176,8 +176,8 @@ class DeleteUser(BaseMutation): else: raise BadRequest("uuid or email must be specified") return DeleteUser(success=True) - except User.DoesNotExist: - raise Http404(f"User with the given uuid: {uuid} or email: {email} does not exist.") + except User.DoesNotExist as dne: + raise Http404(f"User with the given uuid: {uuid} or email: {email} does not exist.") from dne raise PermissionDenied(permission_denied_message) @@ -201,7 +201,7 @@ class ObtainJSONWebToken(BaseMutation): access_token=serializer.validated_data["access"], ) except Exception as e: - raise PermissionDenied(f"invalid credentials provided: {e!s}") + raise PermissionDenied(f"invalid credentials provided: {e!s}") from e class RefreshJSONWebToken(BaseMutation): @@ -222,7 +222,7 @@ class RefreshJSONWebToken(BaseMutation): user=User.objects.get(uuid=serializer.validated_data["user"]["uuid"]), ) except Exception as e: - raise PermissionDenied(f"invalid refresh token provided: {e!s}") + raise PermissionDenied(f"invalid refresh token provided: {e!s}") from e class VerifyJSONWebToken(BaseMutation): @@ -270,7 +270,7 @@ class ActivateUser(BaseMutation): user.save() except (TypeError, ValueError, OverflowError, User.DoesNotExist) as e: - raise BadRequest(_(f"something went wrong: {e!s}")) + raise BadRequest(_(f"something went wrong: {e!s}")) from e return ActivateUser(success=True) @@ -322,23 +322,24 @@ class ConfirmResetPassword(BaseMutation): return ConfirmResetPassword(success=True) except (TypeError, ValueError, OverflowError, ValidationError, User.DoesNotExist) as e: - raise BadRequest(_(f"something went wrong: {e!s}")) + raise BadRequest(_(f"something went wrong: {e!s}")) from e class UploadAvatar(BaseMutation): class Arguments: - avatar = Upload(required=True) + file = Upload(required=True) user = Field(UserType) - def mutate(self, info, avatar): + def mutate(self, info, file): if not info.context.user.is_authenticated: raise PermissionDenied(permission_denied_message) try: - info.context.user.avatar = avatar + info.context.user.avatar = file info.context.user.save() + info.context.user.refresh_from_db() except Exception as e: - raise BadRequest(str(e)) + raise BadRequest(str(e)) from e return UploadAvatar(user=info.context.user) diff --git a/vibes_auth/graphene/object_types.py b/vibes_auth/graphene/object_types.py index 5eeced8f..71c32035 100644 --- a/vibes_auth/graphene/object_types.py +++ b/vibes_auth/graphene/object_types.py @@ -5,7 +5,7 @@ from graphene.types.generic import GenericScalar from graphene_django import DjangoObjectType from graphql_relay.connection.array_connection import connection_from_array -from core.graphene.object_types import OrderType, ProductType, WishlistType +from core.graphene.object_types import OrderType, ProductType, WishlistType, AddressType from core.models import Product, Wishlist from evibes.settings import LANGUAGE_CODE, LANGUAGES from payments.graphene.object_types import BalanceType @@ -47,6 +47,7 @@ class UserType(DjangoObjectType): avatar = String(description=_("avatar")) attributes = GenericScalar(description=_("attributes may be used to store custom data")) language = String(description=_(f"language is one of the {LANGUAGES} with default {LANGUAGE_CODE}")) + addresses = Field(lambda: AddressType, source="address_set", description=_("address set")) class Meta: model = User @@ -97,7 +98,12 @@ class UserType(DjangoObjectType): def resolve_avatar(self: User, info) -> str: if self.avatar: - return info.context.build_absolute_uri(self.avatar.url) + if hasattr(self.avatar, "url"): + return info.context.build_absolute_uri(self.avatar.url) + elif hasattr(self.avatar, "name"): + return info.context.build_absolute_uri(f"/media/{self.avatar.name}") + else: + return info.context.build_absolute_uri(f"/media/{self.avatar}") else: return "" diff --git a/vibes_auth/locale/ar_AR/LC_MESSAGES/django.mo b/vibes_auth/locale/ar_AR/LC_MESSAGES/django.mo index ce885860..f4be54c5 100644 Binary files a/vibes_auth/locale/ar_AR/LC_MESSAGES/django.mo and b/vibes_auth/locale/ar_AR/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/ar_AR/LC_MESSAGES/django.po b/vibes_auth/locale/ar_AR/LC_MESSAGES/django.po index 269fa4db..dfdf1521 100644 --- a/vibes_auth/locale/ar_AR/LC_MESSAGES/django.po +++ b/vibes_auth/locale/ar_AR/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "الرصيد" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "الطلب" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "الطلبات" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "معلومات شخصية" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "الأذونات" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "تواريخ مهمة" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "معلومات إضافية" @@ -70,7 +70,7 @@ msgstr "التحقق من الرمز المميز" msgid "Verify a token (refresh or access)." msgstr "التحقق من الرمز المميز (التحديث أو الوصول)." -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "الرمز المميز صالح" @@ -93,8 +93,8 @@ msgstr "حذف مستخدم" #: vibes_auth/docs/drf/viewsets.py:33 msgid "reset a user's password by sending a reset password email" msgstr "" -"إعادة تعيين كلمة مرور المستخدم عن طريق إرسال بريد إلكتروني لإعادة تعيين كلمة " -"المرور" +"إعادة تعيين كلمة مرور المستخدم عن طريق إرسال بريد إلكتروني لإعادة تعيين كلمة" +" المرور" #: vibes_auth/docs/drf/viewsets.py:38 msgid "handle avatar upload for a user" @@ -105,7 +105,7 @@ msgid "confirm a user's password reset" msgstr "تأكيد إعادة تعيين كلمة مرور المستخدم" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "كلمات المرور غير متطابقة" @@ -132,7 +132,7 @@ msgstr "كلمة المرور ضعيفة جداً" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} غير موجود: {uuid}" +msgstr "{name} غير موجود: {uuid}!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -141,15 +141,15 @@ msgstr "بريد إلكتروني مشوه" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "رقم هاتف مشوّه: {phone_number}" +msgstr "رقم هاتف مشوه: {phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "تنسيق السمة غير صالح: {attribute_pair}" +msgstr "تنسيق السمة غير صالح: {attribute_pair}!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "رابط التفعيل غير صالح!" @@ -161,18 +161,18 @@ msgstr "تم تفعيل الحساب بالفعل..." msgid "something went wrong: {e!s}" msgstr "حدث خطأ ما: {e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "الرمز غير صالح!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "" "المنتجات التي شاهدها هذا المستخدم مؤخرًا (بحد أقصى 48)، بترتيب زمني عكسي." -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "المجموعات" @@ -180,7 +180,7 @@ msgstr "المجموعات" msgid "wishlist" msgstr "قائمة الرغبات" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "الصورة الرمزية" @@ -193,111 +193,120 @@ msgstr "يمكن استخدام السمات لتخزين البيانات ال msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" msgstr "اللغة هي واحدة من {LANGUAGES} مع {LANGUAGE_CODE} الافتراضي" -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "العناوين" + +#: vibes_auth/models.py:85 msgid "email" msgstr "البريد الإلكتروني" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "عنوان البريد الإلكتروني للمستخدم" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "رقم الهاتف" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "رقم هاتف المستخدم" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "الاسم الأول" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "اسم العائلة" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "صورة ملف تعريف المستخدم" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "تم التحقق" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "حالة التحقق من المستخدم" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "نشط" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "قم بإلغاء تحديد هذا بدلاً من حذف الحسابات" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "مشترك" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "حالة اشتراك المستخدم في النشرة الإخبارية" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "رمز التفعيل" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "السمات" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "المستخدم" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "المستخدمون" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "المجموعة" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "الرمز المميز" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "الرموز المميزة المعلقة" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "الرمز المميز المدرج في القائمة السوداء" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "الرموز المميزة المدرجة في القائمة السوداء" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "لم يتم العثور على حساب نشط" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "يجب تعيين سمة token_class على الفئة!" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "تم إدراج الرمز المميز في القائمة السوداء" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "رمز غير صالح" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "لا توجد مطالبة معرف المستخدم في الرمز المميز" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "المستخدم غير موجود" @@ -322,8 +331,7 @@ msgstr "مرحباً %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "" "لقد تلقينا طلباً لإعادة تعيين كلمة المرور الخاصة بك. يرجى إعادة تعيين كلمة " @@ -357,7 +365,7 @@ msgstr "" #: vibes_auth/templates/user_reset_password_email.html:103 #, python-format msgid "best regards,
The %(project_name)s team" -msgstr "مع أطيب تحياتي،
فريق عمل %(project_name)s" +msgstr "مع أطيب التحيات,
فريق %(project_name)s" #: vibes_auth/templates/user_reset_password_email.html:109 #: vibes_auth/templates/user_verification_email.html:108 @@ -389,7 +397,7 @@ msgstr "" #: vibes_auth/templates/user_verification_email.html:102 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "مع أطيب التحيات، فريق عمل %(project_name)s" +msgstr "مع أطيب تحياتي،
فريق %(project_name)s" #: vibes_auth/utils/emailing.py:27 #, python-brace-format @@ -409,17 +417,14 @@ msgstr "" "تنسيق رقم الهاتف غير صالح. يجب إدخال الرقم بالصيغة: \"+999999999\". يُسمح " "بإدخال 15 رقماً كحد أقصى." -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "الرمز المميز غير صالح" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "تمت إعادة تعيين كلمة المرور بنجاح!" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "لقد قمت بتفعيل الحساب بالفعل..." - -#~ msgid "eVibes Auth" -#~ msgstr "مصادقة eVibes Auth" diff --git a/vibes_auth/locale/cs_CZ/LC_MESSAGES/django.mo b/vibes_auth/locale/cs_CZ/LC_MESSAGES/django.mo index 85955205..14060184 100644 Binary files a/vibes_auth/locale/cs_CZ/LC_MESSAGES/django.mo and b/vibes_auth/locale/cs_CZ/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/cs_CZ/LC_MESSAGES/django.po b/vibes_auth/locale/cs_CZ/LC_MESSAGES/django.po index 463f8e62..b901bc0c 100644 --- a/vibes_auth/locale/cs_CZ/LC_MESSAGES/django.po +++ b/vibes_auth/locale/cs_CZ/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "Bilance" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "Objednávka" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "Objednávky" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "Osobní informace" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "Oprávnění" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "Důležitá data" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "Další informace" @@ -70,7 +70,7 @@ msgstr "Ověření tokenu" msgid "Verify a token (refresh or access)." msgstr "Ověření tokenu (obnovení nebo přístup)." -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "Token je platný" @@ -103,7 +103,7 @@ msgid "confirm a user's password reset" msgstr "Potvrzení obnovení hesla uživatele" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "Hesla se neshodují" @@ -130,7 +130,7 @@ msgstr "Heslo je příliš slabé" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} neexistuje: {uuid}" +msgstr "{name} neexistuje: {uuid}!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -139,15 +139,15 @@ msgstr "Špatně formulovaný e-mail" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "Chybně zadané telefonní číslo: {phone_number}" +msgstr "Chybně zadané telefonní číslo: {phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "Nesprávný formát atributu: {attribute_pair}" +msgstr "Nesprávný formát atributu: {attribute_pair}!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "Aktivační odkaz je neplatný!" @@ -159,19 +159,19 @@ msgstr "Účet byl již aktivován..." msgid "something went wrong: {e!s}" msgstr "Něco se pokazilo: {e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "Token je neplatný!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "" "Produkty, které si tento uživatel prohlížel naposledy (max. 48), seřazené v " "opačném pořadí." -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "Skupiny" @@ -179,7 +179,7 @@ msgstr "Skupiny" msgid "wishlist" msgstr "Seznam přání" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "Avatar" @@ -190,113 +190,122 @@ msgstr "Atributy lze použít k uložení vlastních dat." #: vibes_auth/graphene/object_types.py:49 #, python-brace-format msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" -msgstr "Jazyk je jeden z {LANGUAGES} s výchozím {LANGUAGE_CODE}." +msgstr "Jazyk je jeden z {LANGUAGES} s výchozím {LANGUAGE_CODE}" -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "Adresy" + +#: vibes_auth/models.py:85 msgid "email" msgstr "E-mail" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "E-mailová adresa uživatele" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "Telefonní číslo" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "Telefonní číslo uživatele" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "Křestní jméno" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "Příjmení" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "Obrázek profilu uživatele" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "Je ověřeno" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "Stav ověření uživatele" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "Je aktivní" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "Zrušení výběru této možnosti místo odstranění účtů" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "Je přihlášena k odběru" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "Stav odběru newsletteru uživatele" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "Aktivační token" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "Atributy" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "Uživatel" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "Uživatelé" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "Skupina" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "Vynikající žeton" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "Nevyplacené žetony" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "Token na černé listině" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "Tokeny na černé listině" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "Nebyl nalezen žádný aktivní účet" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "Musí být nastaven atribut token_class na třídě!" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "Token na černé listině" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "Neplatný token" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "V tokenu není deklarace uuid uživatele" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "Uživatel neexistuje" @@ -321,8 +330,7 @@ msgstr "Ahoj %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "" "Obdrželi jsme žádost o obnovení vašeho hesla. Kliknutím na níže uvedené " @@ -342,8 +350,7 @@ msgid "" "if the button above does not work, please copy and paste the following URL\n" " into your web browser:" msgstr "" -"Pokud výše uvedené tlačítko nefunguje, zkopírujte a vložte následující " -"adresu URL\n" +"Pokud výše uvedené tlačítko nefunguje, zkopírujte a vložte následující adresu URL\n" " do webového prohlížeče:" #: vibes_auth/templates/user_reset_password_email.html:101 @@ -409,17 +416,14 @@ msgstr "" "Nesprávný formát telefonního čísla. Číslo musí být zadáno ve formátu: " "\"+999999999\". Povoleno je až 15 číslic." -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "Token je neplatný" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "Heslo bylo úspěšně resetováno!" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "Účet jste již aktivovali..." - -#~ msgid "eVibes Auth" -#~ msgstr "eVibes Auth" diff --git a/vibes_auth/locale/da_DK/LC_MESSAGES/django.mo b/vibes_auth/locale/da_DK/LC_MESSAGES/django.mo index 53aeb3e3..7380dad2 100644 Binary files a/vibes_auth/locale/da_DK/LC_MESSAGES/django.mo and b/vibes_auth/locale/da_DK/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/da_DK/LC_MESSAGES/django.po b/vibes_auth/locale/da_DK/LC_MESSAGES/django.po index a045f38f..dd76906d 100644 --- a/vibes_auth/locale/da_DK/LC_MESSAGES/django.po +++ b/vibes_auth/locale/da_DK/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "Balance" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "Bestil" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "Bestillinger" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "Personlig information" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "Tilladelser" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "Vigtige datoer" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "Yderligere information" @@ -70,7 +70,7 @@ msgstr "Bekræft et token" msgid "Verify a token (refresh or access)." msgstr "Bekræft et token (opdatering eller adgang)." -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "Tokenet er gyldigt" @@ -105,7 +105,7 @@ msgid "confirm a user's password reset" msgstr "Bekræft nulstilling af en brugers adgangskode" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "Adgangskoderne stemmer ikke overens" @@ -132,7 +132,7 @@ msgstr "Adgangskoden er for svag" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} findes ikke: {uuid}" +msgstr "{name} findes ikke: {uuid}!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -141,15 +141,15 @@ msgstr "Misdannet e-mail" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "Misdannet telefonnummer: {phone_number}." +msgstr "Misdannet telefonnummer: {phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "Ugyldigt attributformat: {attribute_pair}" +msgstr "Ugyldigt attributformat: {attribute_pair}!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "Aktiveringslinket er ugyldigt!" @@ -161,19 +161,19 @@ msgstr "Kontoen er allerede aktiveret..." msgid "something went wrong: {e!s}" msgstr "Noget gik galt: {e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "Token er ugyldig!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "" "De produkter, som denne bruger har set for nylig (maks. 48), i omvendt " "kronologisk rækkefølge." -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "Grupper" @@ -181,7 +181,7 @@ msgstr "Grupper" msgid "wishlist" msgstr "Ønskeliste" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "Avatar" @@ -192,113 +192,122 @@ msgstr "Attributter kan bruges til at gemme brugerdefinerede data" #: vibes_auth/graphene/object_types.py:49 #, python-brace-format msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" -msgstr "Sprog er et af {LANGUAGES} med standard {LANGUAGE_CODE}." +msgstr "Sprog er en af {LANGUAGES} med standard {LANGUAGE_CODE}." -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "Adresser" + +#: vibes_auth/models.py:85 msgid "email" msgstr "E-mail" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "Brugerens e-mailadresse" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "Telefonnummer" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "Brugerens telefonnummer" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "Fornavn" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "Efternavn" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "Billede af brugerprofil" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "Er verificeret" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "Brugerens verifikationsstatus" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "Er aktiv" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "Fravælg dette i stedet for at slette konti" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "Er tilmeldt" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "Status for brugerens abonnement på nyhedsbrev" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "Aktiveringstoken" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "Egenskaber" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "Bruger" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "Brugere" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "Gruppe" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "Enestående token" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "Udestående tokens" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "Sortlistet token" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "Sortlistede tokens" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "Ingen aktiv konto fundet" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "Skal sætte token_class-attributten på klassen!" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "Token blacklistet" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "Ugyldigt token" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "Ingen bruger-uuid-krav til stede i token" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "Brugeren findes ikke" @@ -323,8 +332,7 @@ msgstr "Hej %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "" "Vi har modtaget en anmodning om at nulstille din adgangskode. Nulstil " @@ -344,8 +352,7 @@ msgid "" "if the button above does not work, please copy and paste the following URL\n" " into your web browser:" msgstr "" -"Hvis ovenstående knap ikke virker, bedes du kopiere og indsætte følgende " -"URL\n" +"Hvis ovenstående knap ikke virker, bedes du kopiere og indsætte følgende URL\n" " i din webbrowser:" #: vibes_auth/templates/user_reset_password_email.html:101 @@ -358,7 +365,7 @@ msgstr "" #: vibes_auth/templates/user_reset_password_email.html:103 #, python-format msgid "best regards,
The %(project_name)s team" -msgstr "Med venlig hilsen,
%(project_name)s team" +msgstr "Bedste hilsner,
The %(project_name)s team" #: vibes_auth/templates/user_reset_password_email.html:109 #: vibes_auth/templates/user_verification_email.html:108 @@ -390,7 +397,7 @@ msgstr "" #: vibes_auth/templates/user_verification_email.html:102 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Med venlig hilsen,
%(project_name)s team" +msgstr "Med venlig hilsen,
teamet %(project_name)s." #: vibes_auth/utils/emailing.py:27 #, python-brace-format @@ -410,17 +417,14 @@ msgstr "" "Ugyldigt telefonnummerformat. Nummeret skal indtastes i formatet: " "\"+999999999\". Op til 15 cifre er tilladt." -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "Tokenet er ugyldigt" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "Adgangskoden er blevet nulstillet med succes!" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "Du har allerede aktiveret kontoen..." - -#~ msgid "eVibes Auth" -#~ msgstr "eVibes Auth" diff --git a/vibes_auth/locale/de_DE/LC_MESSAGES/django.mo b/vibes_auth/locale/de_DE/LC_MESSAGES/django.mo index 5873aab8..7c5c9893 100644 Binary files a/vibes_auth/locale/de_DE/LC_MESSAGES/django.mo and b/vibes_auth/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/de_DE/LC_MESSAGES/django.po b/vibes_auth/locale/de_DE/LC_MESSAGES/django.po index 8d2a35b5..10c66cc0 100644 --- a/vibes_auth/locale/de_DE/LC_MESSAGES/django.po +++ b/vibes_auth/locale/de_DE/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "Waage" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "Bestellung" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "Bestellungen" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "Persönliche Informationen" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "Erlaubnisse" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "Wichtige Termine" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "Zusätzliche Informationen" @@ -71,7 +71,7 @@ msgstr "Überprüfen eines Tokens" msgid "Verify a token (refresh or access)." msgstr "Überprüfen eines Tokens (Aktualisierung oder Zugriff)." -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "Das Token ist gültig" @@ -106,7 +106,7 @@ msgid "confirm a user's password reset" msgstr "Bestätigen Sie das Zurücksetzen des Passworts eines Benutzers" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "Passwörter stimmen nicht überein" @@ -126,8 +126,8 @@ msgstr "" #: vibes_auth/graphene/mutations.py:41 msgid "the user's b64-encoded uuid who referred the new user to us." msgstr "" -"Die b64-kodierte uuid des Benutzers, der den neuen Benutzer an uns verwiesen " -"hat." +"Die b64-kodierte uuid des Benutzers, der den neuen Benutzer an uns verwiesen" +" hat." #: vibes_auth/graphene/mutations.py:61 msgid "password too weak" @@ -136,7 +136,7 @@ msgstr "Das Passwort ist zu schwach" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} existiert nicht: {uuid}" +msgstr "{name} existiert nicht: {uuid}!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -145,15 +145,15 @@ msgstr "Fehlerhafte E-Mail" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "Fehlerhafte Telefonnummer: {phone_number}" +msgstr "Missgebildete Telefonnummer: {phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "Ungültiges Attributformat: {attribute_pair}" +msgstr "Ungültiges Attributformat: {attribute_pair}!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "Der Aktivierungslink ist ungültig!" @@ -165,19 +165,19 @@ msgstr "Das Konto wurde bereits aktiviert..." msgid "something went wrong: {e!s}" msgstr "Etwas ist schief gelaufen: {e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "Token ist ungültig!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "" "Die Produkte, die dieser Benutzer zuletzt angesehen hat (maximal 48), in " "umgekehrter chronologischer Reihenfolge." -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "Gruppen" @@ -185,7 +185,7 @@ msgstr "Gruppen" msgid "wishlist" msgstr "Wunschzettel" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "Avatar" @@ -197,113 +197,122 @@ msgstr "" #: vibes_auth/graphene/object_types.py:49 #, python-brace-format msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" -msgstr "Sprache ist eine der {LANGUAGES} mit Standard {LANGUAGE_CODE}" +msgstr "Sprache ist eine der {LANGUAGES} mit Voreinstellung {LANGUAGE_CODE}" -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "Adressen" + +#: vibes_auth/models.py:85 msgid "email" msgstr "E-Mail" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "E-Mail Adresse des Benutzers" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "Rufnummer" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "Rufnummer des Benutzers" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "Vornamen" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "Nachname" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "Bild des Benutzerprofils" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "Wird überprüft" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "Verifizierungsstatus des Benutzers" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "Ist aktiv" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "Deaktivieren Sie diese Option, anstatt Konten zu löschen" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "Ist abonniert" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "Status des Newsletter-Abonnements des Benutzers" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "Aktivierungs-Token" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "Attribute" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "Benutzer" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "Benutzer" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "Gruppe" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "Hervorragende Wertmarke" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "Ausstehende Wertmarken" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "Token auf der schwarzen Liste" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "Token auf der schwarzen Liste" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "Kein aktives Konto gefunden" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "Das Attribut token_class muss auf class gesetzt werden!" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "Token auf der schwarzen Liste" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "Ungültiges Token" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "Kein Benutzer uuid-Anspruch im Token vorhanden" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "Benutzer existiert nicht" @@ -328,8 +337,7 @@ msgstr "Hallo %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "" "Wir haben eine Anfrage erhalten, Ihr Passwort zurückzusetzen. Bitte setzen " @@ -349,8 +357,7 @@ msgid "" "if the button above does not work, please copy and paste the following URL\n" " into your web browser:" msgstr "" -"Wenn die obige Schaltfläche nicht funktioniert, kopieren Sie bitte die " -"folgende URL und fügen Sie sie in Ihren Browser ein\n" +"Wenn die obige Schaltfläche nicht funktioniert, kopieren Sie bitte die folgende URL und fügen Sie sie in Ihren Browser ein\n" " in Ihren Webbrowser ein:" #: vibes_auth/templates/user_reset_password_email.html:101 @@ -358,13 +365,13 @@ msgid "" "if you did not send this request, please ignore this\n" " email." msgstr "" -"Wenn Sie diese Anfrage nicht gesendet haben, ignorieren Sie bitte diese E-" -"Mail." +"Wenn Sie diese Anfrage nicht gesendet haben, ignorieren Sie bitte diese " +"E-Mail." #: vibes_auth/templates/user_reset_password_email.html:103 #, python-format msgid "best regards,
The %(project_name)s team" -msgstr "Mit freundlichen Grüßen,
Das Team von %(project_name)s" +msgstr "Mit freundlichen Grüßen,
Das %(project_name)s-Team" #: vibes_auth/templates/user_reset_password_email.html:109 #: vibes_auth/templates/user_verification_email.html:108 @@ -396,12 +403,12 @@ msgstr "" #: vibes_auth/templates/user_verification_email.html:102 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Mit freundlichen Grüßen,
das %(project_name)s Team" +msgstr "Mit freundlichen Grüßen,
das %(project_name)s-Team" #: vibes_auth/utils/emailing.py:27 #, python-brace-format msgid "{config.PROJECT_NAME} | Activate Account" -msgstr "{config.PROJECT_NAME} | Konto aktivieren" +msgstr "{config.PROJECT_NAME} | Konto freischalten" #: vibes_auth/utils/emailing.py:69 #, python-brace-format @@ -416,17 +423,14 @@ msgstr "" "Ungültiges Telefonnummernformat. Die Nummer muss in dem Format eingegeben " "werden: \"+999999999\". Bis zu 15 Ziffern sind erlaubt." -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "Das Token ist ungültig" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "Das Passwort wurde erfolgreich zurückgesetzt!" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "Sie haben das Konto bereits aktiviert..." - -#~ msgid "eVibes Auth" -#~ msgstr "eVibes Auth" diff --git a/vibes_auth/locale/en_GB/LC_MESSAGES/django.mo b/vibes_auth/locale/en_GB/LC_MESSAGES/django.mo index 3bd5e573..5b5288c3 100644 Binary files a/vibes_auth/locale/en_GB/LC_MESSAGES/django.mo and b/vibes_auth/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/en_GB/LC_MESSAGES/django.po b/vibes_auth/locale/en_GB/LC_MESSAGES/django.po index 69c069f4..409ecaef 100644 --- a/vibes_auth/locale/en_GB/LC_MESSAGES/django.po +++ b/vibes_auth/locale/en_GB/LC_MESSAGES/django.po @@ -5,9 +5,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -22,27 +22,27 @@ msgstr "" msgid "balance" msgstr "Balance" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "Order" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "Orders" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "Personal Info" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "Permissions" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "Important dates" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "Additional Info" @@ -74,7 +74,7 @@ msgstr "Verify a token" msgid "Verify a token (refresh or access)." msgstr "Verify a token (refresh or access)." -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "The token is valid" @@ -107,7 +107,7 @@ msgid "confirm a user's password reset" msgstr "Confirm a user's password reset" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "Passwords do not match" @@ -134,7 +134,7 @@ msgstr "The password is too weak" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} does not exist: {uuid}" +msgstr "{name} does not exist: {uuid}!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -143,15 +143,15 @@ msgstr "Malformed email" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "Malformed phone number: {phone_number}" +msgstr "Malformed phone number: {phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "Invalid attribute format: {attribute_pair}" +msgstr "Invalid attribute format: {attribute_pair}!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "Activation link is invalid!" @@ -163,19 +163,19 @@ msgstr "Account has been already activated..." msgid "something went wrong: {e!s}" msgstr "Something went wrong: {e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "Token is invalid!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "" "The products this user has viewed most recently (max 48), in reverse-" "chronological order." -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "Groups" @@ -183,7 +183,7 @@ msgstr "Groups" msgid "wishlist" msgstr "Wishlist" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "Avatar" @@ -196,111 +196,120 @@ msgstr "Attributes may be used to store custom data" msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" msgstr "Language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "Adresses" + +#: vibes_auth/models.py:85 msgid "email" msgstr "E-mail" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "User's email address" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "Phone Number" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "User phone number" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "First name" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "Last name" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "User profile image" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "Is verified" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "User's verification status" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "Is active" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "Unselect this instead of deleting accounts" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "Is subscribed" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "User's newsletter subscription status" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "Activation token" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "Attributes" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "User" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "Users" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "Group" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "Outstanding token" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "Outstanding tokens" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "Blacklisted token" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "Blacklisted tokens" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "No active account found" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "Must set token_class attribute on class!" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "Token blacklisted" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "Invalid token" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "No user uuid claim present in token" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "User does not exist" @@ -325,8 +334,7 @@ msgstr "Hello %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "" "We have received a request to reset your password. Please reset your " @@ -412,37 +420,14 @@ msgstr "" "Invalid phone number format. The number must be entered in the format: " "\"+999999999\". Up to 15 digits allowed." -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "The token is invalid" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "Password has been reset successfully!" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "You have already activated the account..." - -#~ msgid "eVibes Auth" -#~ msgstr "eVibes Auth" - -#~ msgid "reset password" -#~ msgstr "Reset password" - -#~ msgid "" -#~ "if the button above does not work, please copy and paste the following " -#~ "URL into your web browser:" -#~ msgstr "" -#~ "If the button above does not work, please copy and paste the following " -#~ "URL into your web browser:" - -#, python-brace-format -#~ msgid "user not found with the given pk: {user_pk}" -#~ msgstr "User not found with the given UUID: {user_pk}" - -#~ msgid "something went wrong while sending an email: {e!s}" -#~ msgstr "Something went wrong while sending an email: {e!s}" - -#~ msgid "recently viwed" -#~ msgstr "Recently viewed" diff --git a/vibes_auth/locale/en_US/LC_MESSAGES/django.mo b/vibes_auth/locale/en_US/LC_MESSAGES/django.mo index d083bc4b..b5c06dbf 100644 Binary files a/vibes_auth/locale/en_US/LC_MESSAGES/django.mo and b/vibes_auth/locale/en_US/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/en_US/LC_MESSAGES/django.po b/vibes_auth/locale/en_US/LC_MESSAGES/django.po index cbf93d02..667df87e 100644 --- a/vibes_auth/locale/en_US/LC_MESSAGES/django.po +++ b/vibes_auth/locale/en_US/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "Balance" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "Order" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "Orders" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "Personal Info" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "Permissions" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "Important dates" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "Additional Info" @@ -70,7 +70,7 @@ msgstr "Verify a token" msgid "Verify a token (refresh or access)." msgstr "Verify a token (refresh or access)." -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "The token is valid" @@ -103,7 +103,7 @@ msgid "confirm a user's password reset" msgstr "Confirm a user's password reset" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "Passwords do not match" @@ -130,7 +130,7 @@ msgstr "The password is too weak" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} does not exist: {uuid}" +msgstr "{name} does not exist: {uuid}!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -139,15 +139,15 @@ msgstr "Malformed email" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "Malformed phone number: {phone_number}" +msgstr "Malformed phone number: {phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "Invalid attribute format: {attribute_pair}" +msgstr "Invalid attribute format: {attribute_pair}!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "Activation link is invalid!" @@ -159,19 +159,19 @@ msgstr "Account has been already activated..." msgid "something went wrong: {e!s}" msgstr "Something went wrong: {e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "Token is invalid!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "" "The products this user has viewed most recently (max 48), in reverse-" "chronological order." -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "Groups" @@ -179,7 +179,7 @@ msgstr "Groups" msgid "wishlist" msgstr "Wishlist" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "Avatar" @@ -192,111 +192,120 @@ msgstr "Attributes may be used to store custom data" msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" msgstr "Language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "Adresses" + +#: vibes_auth/models.py:85 msgid "email" msgstr "Email" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "User's email address" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "Phone Number" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "User phone number" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "First name" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "Last name" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "User profile image" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "Is verified" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "User's verification status" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "Is active" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "Unselect this instead of deleting accounts" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "Is subscribed" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "User's newsletter subscription status" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "Activation token" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "Attributes" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "User" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "Users" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "Group" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "Outstanding token" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "Outstanding tokens" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "Blacklisted token" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "Blacklisted tokens" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "No active account found" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "Must set token_class attribute on class!" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "Token blacklisted" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "Invalid token" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "No user uuid claim present in token" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "User does not exist" @@ -321,8 +330,7 @@ msgstr "Hello %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "" "We have received a request to reset your password. Please reset your " @@ -408,17 +416,14 @@ msgstr "" "Invalid phone number format. The number must be entered in the format: " "\"+999999999\". Up to 15 digits allowed." -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "The token is invalid" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "Password has been reset successfully!" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "You have already activated the account..." - -#~ msgid "eVibes Auth" -#~ msgstr "eVibes Auth" diff --git a/vibes_auth/locale/es_ES/LC_MESSAGES/django.mo b/vibes_auth/locale/es_ES/LC_MESSAGES/django.mo index f322f54f..cd06e2c8 100644 Binary files a/vibes_auth/locale/es_ES/LC_MESSAGES/django.mo and b/vibes_auth/locale/es_ES/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/es_ES/LC_MESSAGES/django.po b/vibes_auth/locale/es_ES/LC_MESSAGES/django.po index f51db134..01ca6613 100644 --- a/vibes_auth/locale/es_ES/LC_MESSAGES/django.po +++ b/vibes_auth/locale/es_ES/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "Saldo" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "Pida" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "Pedidos" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "Información personal" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "Permisos" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "Fechas importantes" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "Información adicional" @@ -70,7 +70,7 @@ msgstr "Verificar un token" msgid "Verify a token (refresh or access)." msgstr "Verificar un token (actualización o acceso)." -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "El token es válido" @@ -105,7 +105,7 @@ msgid "confirm a user's password reset" msgstr "Confirmar el restablecimiento de la contraseña de un usuario" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "Las contraseñas no coinciden" @@ -133,7 +133,7 @@ msgstr "La contraseña es demasiado débil" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} no existe: {uuid}" +msgstr "{name} no existe: ¡{uuid}!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -142,15 +142,15 @@ msgstr "Correo electrónico malformado" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "Número de teléfono malformado: {phone_number}" +msgstr "Número de teléfono malformado: ¡{phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "Formato de atributo no válido: {attribute_pair}" +msgstr "Formato de atributo no válido: ¡{attribute_pair}!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "El enlace de activación no es válido." @@ -162,19 +162,19 @@ msgstr "La cuenta ya ha sido activada..." msgid "something went wrong: {e!s}" msgstr "Algo salió mal: {e!s}." -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "¡La ficha no es válida!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "" "Los productos que este usuario ha visto más recientemente (máx. 48), en " "orden cronológico inverso." -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "Grupos" @@ -182,7 +182,7 @@ msgstr "Grupos" msgid "wishlist" msgstr "Lista de deseos" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "Avatar" @@ -193,113 +193,122 @@ msgstr "Los atributos pueden utilizarse para almacenar datos personalizados" #: vibes_auth/graphene/object_types.py:49 #, python-brace-format msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" -msgstr "El idioma es uno de los {LANGUAGES} con {LANGUAGE_CODE} por defecto." +msgstr "El idioma es uno de los {LANGUAGES} con {LANGUAGE_CODE} por defecto" -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "Direcciones" + +#: vibes_auth/models.py:85 msgid "email" msgstr "Correo electrónico" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "Dirección de correo electrónico del usuario" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "Número de teléfono" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "Número de teléfono del usuario" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "Nombre" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "Apellido" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "Imagen del perfil del usuario" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "Se verifica" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "Estado de verificación del usuario" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "Está activo" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "Deseleccione esta opción en lugar de eliminar cuentas" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "Está suscrito" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "Estado de suscripción del usuario al boletín" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "Ficha de activación" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "Atributos" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "Usuario" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "Usuarios" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "Grupo" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "Ficha pendiente" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "Fichas pendientes" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "Ficha en la lista negra" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "Fichas en la lista negra" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "No se ha encontrado ninguna cuenta activa" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "Debe establecer el atributo token_class en la clase." + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "Ficha en la lista negra" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "Token no válido" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "No user uuid claim present in token" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "El usuario no existe" @@ -324,8 +333,7 @@ msgstr "Hola %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "" "Hemos recibido una solicitud para restablecer su contraseña. Por favor, " @@ -359,7 +367,7 @@ msgstr "" #: vibes_auth/templates/user_reset_password_email.html:103 #, python-format msgid "best regards,
The %(project_name)s team" -msgstr "Saludos cordiales,
El equipo de %(project_name)s" +msgstr "Saludos cordiales,
El equipo %(project_name)s" #: vibes_auth/templates/user_reset_password_email.html:109 #: vibes_auth/templates/user_verification_email.html:108 @@ -391,7 +399,7 @@ msgstr "" #: vibes_auth/templates/user_verification_email.html:102 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Saludos cordiales,
el equipo de %(project_name)s" +msgstr "Saludos cordiales,
el equipo %(project_name)s" #: vibes_auth/utils/emailing.py:27 #, python-brace-format @@ -411,17 +419,14 @@ msgstr "" "Formato de número de teléfono no válido. El número debe introducirse con el " "formato \"+999999999\". Se permiten hasta 15 dígitos." -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "El token no es válido" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "La contraseña se ha restablecido correctamente." -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "Ya ha activado la cuenta..." - -#~ msgid "eVibes Auth" -#~ msgstr "eVibes Auth" diff --git a/vibes_auth/locale/fr_FR/LC_MESSAGES/django.mo b/vibes_auth/locale/fr_FR/LC_MESSAGES/django.mo index 3cadc87d..31480c06 100644 Binary files a/vibes_auth/locale/fr_FR/LC_MESSAGES/django.mo and b/vibes_auth/locale/fr_FR/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/fr_FR/LC_MESSAGES/django.po b/vibes_auth/locale/fr_FR/LC_MESSAGES/django.po index ab1f4ec8..9ef1405c 100644 --- a/vibes_auth/locale/fr_FR/LC_MESSAGES/django.po +++ b/vibes_auth/locale/fr_FR/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "Balance" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "Commande" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "Commandes" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "Informations personnelles" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "Permissions" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "Important dates" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "Informations complémentaires" @@ -72,7 +72,7 @@ msgstr "Vérifier un jeton" msgid "Verify a token (refresh or access)." msgstr "Vérifier un jeton (rafraîchissement ou accès)." -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "Le jeton est valide" @@ -107,7 +107,7 @@ msgid "confirm a user's password reset" msgstr "Confirmer la réinitialisation du mot de passe d'un utilisateur" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "Les mots de passe ne correspondent pas" @@ -136,7 +136,7 @@ msgstr "Le mot de passe est trop faible" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} n'existe pas : {uuid}" +msgstr "{name} n'existe pas : {uuid} !" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -145,15 +145,15 @@ msgstr "Courriel malformé" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "Numéro de téléphone malformé : {phone_number}" +msgstr "Numéro de téléphone malformé : {phone_number} !" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "Format d'attribut non valide : {attribute_pair}" +msgstr "Format d'attribut non valide : {attribute_pair} !" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "Le lien d'activation n'est pas valide !" @@ -165,19 +165,19 @@ msgstr "Le compte a déjà été activé..." msgid "something went wrong: {e!s}" msgstr "Quelque chose a mal tourné : {e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "Le jeton n'est pas valide !" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "" -"Les produits que cet utilisateur a consultés le plus récemment (max 48), par " -"ordre chronologique inverse." +"Les produits que cet utilisateur a consultés le plus récemment (max 48), par" +" ordre chronologique inverse." -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "Groupes" @@ -185,7 +185,7 @@ msgstr "Groupes" msgid "wishlist" msgstr "Liste de souhaits" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "Avatar" @@ -201,111 +201,121 @@ msgstr "" "La langue est l'une des {LANGUAGES} avec la valeur par défaut " "{LANGUAGE_CODE}." -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "Adresses" + +#: vibes_auth/models.py:85 msgid "email" msgstr "Courriel" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "Adresse électronique de l'utilisateur" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "Numéro de téléphone" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "Numéro de téléphone de l'utilisateur" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "Prénom" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "Nom de famille" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "Image du profil de l'utilisateur" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "Est vérifié" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "Statut de vérification de l'utilisateur" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "Est actif" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "Désélectionner cette option au lieu de supprimer des comptes" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "Est abonné" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "Statut de l'abonnement à la lettre d'information de l'utilisateur" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "Jeton d'activation" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "Attributs" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "Utilisateur" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "Utilisateurs" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "Groupe" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "Jeton exceptionnel" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "Jetons en circulation" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "Jeton sur liste noire" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "Jetons sur liste noire" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "Aucun compte actif trouvé" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "L'attribut token_class doit être défini sur la classe !" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "Token sur liste noire" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "Jeton non valide" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" -msgstr "Aucune revendication d'uuid d'utilisateur n'est présente dans le jeton" +msgstr "" +"Aucune revendication d'uuid d'utilisateur n'est présente dans le jeton" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "L'utilisateur n'existe pas" @@ -330,8 +340,7 @@ msgstr "Bonjour %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "" "Nous avons reçu une demande de réinitialisation de votre mot de passe. " @@ -352,8 +361,7 @@ msgid "" "if the button above does not work, please copy and paste the following URL\n" " into your web browser:" msgstr "" -"Si le bouton ci-dessus ne fonctionne pas, veuillez copier et coller l'URL " -"suivante\n" +"Si le bouton ci-dessus ne fonctionne pas, veuillez copier et coller l'URL suivante\n" " suivante dans votre navigateur web :" #: vibes_auth/templates/user_reset_password_email.html:101 @@ -367,7 +375,7 @@ msgstr "" #: vibes_auth/templates/user_reset_password_email.html:103 #, python-format msgid "best regards,
The %(project_name)s team" -msgstr "Meilleures salutations,
L'équipe de %(project_name)s" +msgstr "Meilleures salutations,
L'équipe %(project_name)s" #: vibes_auth/templates/user_reset_password_email.html:109 #: vibes_auth/templates/user_verification_email.html:108 @@ -385,8 +393,8 @@ msgid "" "thank you for signing up for %(project_name)s. please activate your account\n" " by clicking the button below:" msgstr "" -"Merci de vous être inscrit à %(project_name)s. Veuillez activer votre compte " -"en cliquant sur le bouton ci-dessous :" +"Merci de vous être inscrit à %(project_name)s. Veuillez activer votre compte" +" en cliquant sur le bouton ci-dessous :" #: vibes_auth/templates/user_verification_email.html:96 msgid "" @@ -399,7 +407,7 @@ msgstr "" #: vibes_auth/templates/user_verification_email.html:102 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Meilleures salutations,
l'équipe de %(project_name)s" +msgstr "Meilleures salutations,
l'équipe %(project_name)s" #: vibes_auth/utils/emailing.py:27 #, python-brace-format @@ -419,17 +427,14 @@ msgstr "" "Format de numéro de téléphone non valide. Le numéro doit être saisi au " "format : \"+999999999\". Un maximum de 15 chiffres est autorisé." -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "Le jeton n'est pas valide" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "Le mot de passe a été réinitialisé avec succès !" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "Vous avez déjà activé le compte..." - -#~ msgid "eVibes Auth" -#~ msgstr "eVibes Auth" diff --git a/vibes_auth/locale/hi_IN/LC_MESSAGES/django.mo b/vibes_auth/locale/hi_IN/LC_MESSAGES/django.mo index 0fc354f2..47c1f925 100644 Binary files a/vibes_auth/locale/hi_IN/LC_MESSAGES/django.mo and b/vibes_auth/locale/hi_IN/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/hi_IN/LC_MESSAGES/django.po b/vibes_auth/locale/hi_IN/LC_MESSAGES/django.po index bb8f1f37..8f4f37a3 100644 --- a/vibes_auth/locale/hi_IN/LC_MESSAGES/django.po +++ b/vibes_auth/locale/hi_IN/LC_MESSAGES/django.po @@ -5,9 +5,9 @@ # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -21,27 +21,27 @@ msgstr "" msgid "balance" msgstr "" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "" @@ -73,7 +73,7 @@ msgstr "" msgid "Verify a token (refresh or access)." msgstr "" -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "" @@ -106,7 +106,7 @@ msgid "confirm a user's password reset" msgstr "" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "" @@ -149,8 +149,8 @@ msgstr "" msgid "Invalid attribute format: {attribute_pair}" msgstr "" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "" @@ -162,7 +162,7 @@ msgstr "" msgid "something went wrong: {e!s}" msgstr "" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "" @@ -172,7 +172,7 @@ msgid "" "chronological order" msgstr "" -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "" @@ -180,7 +180,7 @@ msgstr "" msgid "wishlist" msgstr "" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "" @@ -193,111 +193,120 @@ msgstr "" msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" msgstr "" -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "" + +#: vibes_auth/models.py:85 msgid "email" msgstr "" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "" @@ -395,14 +404,14 @@ msgid "" "\"+999999999\". up to 15 digits allowed." msgstr "" -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "" diff --git a/vibes_auth/locale/it_IT/LC_MESSAGES/django.mo b/vibes_auth/locale/it_IT/LC_MESSAGES/django.mo index 0e6595ee..2c428447 100644 Binary files a/vibes_auth/locale/it_IT/LC_MESSAGES/django.mo and b/vibes_auth/locale/it_IT/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/it_IT/LC_MESSAGES/django.po b/vibes_auth/locale/it_IT/LC_MESSAGES/django.po index 2fb50c91..539c85fb 100644 --- a/vibes_auth/locale/it_IT/LC_MESSAGES/django.po +++ b/vibes_auth/locale/it_IT/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "Equilibrio" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "Ordine" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "Ordini" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "Informazioni personali" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "Permessi" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "Date importanti" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "Ulteriori informazioni" @@ -71,7 +71,7 @@ msgstr "Verifica di un token" msgid "Verify a token (refresh or access)." msgstr "Verifica di un token (aggiornamento o accesso)." -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "Il token è valido" @@ -106,7 +106,7 @@ msgid "confirm a user's password reset" msgstr "Confermare la reimpostazione della password di un utente" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "Le password non corrispondono" @@ -133,7 +133,7 @@ msgstr "La password è troppo debole" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} non esiste: {uuid}" +msgstr "{name} non esiste: {uuid}!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -142,15 +142,15 @@ msgstr "Email malformata" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "Numero di telefono malformato: {phone_number}" +msgstr "Numero di telefono malformato: {phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "Formato attributo non valido: {attribute_pair}" +msgstr "Formato attributo non valido: {attribute_pair}!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "Il link di attivazione non è valido!" @@ -162,19 +162,19 @@ msgstr "L'account è già stato attivato..." msgid "something went wrong: {e!s}" msgstr "Qualcosa è andato storto: {e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "Il gettone non è valido!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "" "I prodotti che questo utente ha visualizzato più di recente (max 48), in " "ordine cronologico inverso." -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "Gruppi" @@ -182,7 +182,7 @@ msgstr "Gruppi" msgid "wishlist" msgstr "Lista dei desideri" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "Avatar" @@ -197,111 +197,120 @@ msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" msgstr "" "La lingua è una delle {LANGUAGES} con il codice predefinito {LANGUAGE_CODE}." -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "Indirizzi" + +#: vibes_auth/models.py:85 msgid "email" msgstr "Email" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "Indirizzo e-mail dell'utente" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "Numero di telefono" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "Numero di telefono dell'utente" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "Nome" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "Cognome" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "Immagine del profilo utente" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "È verificato" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "Stato di verifica dell'utente" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "È attivo" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "Deselezionare questa opzione invece di eliminare gli account" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "È iscritto" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "Stato di iscrizione alla newsletter dell'utente" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "Token di attivazione" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "Attributi" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "Utente" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "Utenti" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "Gruppo" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "Gettone eccezionale" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "Gettoni in sospeso" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "Token in lista nera" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "Gettoni nella lista nera" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "Nessun conto attivo trovato" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "Deve essere impostato l'attributo token_class sulla classe!" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "Token nella lista nera" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "Token non valido" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "Nessuna richiesta di uuid utente presente nel token" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "L'utente non esiste" @@ -322,12 +331,11 @@ msgstr "Conferma della reimpostazione della password" #: vibes_auth/templates/user_verification_email.html:91 #, python-format msgid "hello %(user_first_name)s," -msgstr "Ciao %(user_first_name)s," +msgstr "Hello %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "" "Abbiamo ricevuto una richiesta di reimpostazione della password. La " @@ -361,7 +369,7 @@ msgstr "" #: vibes_auth/templates/user_reset_password_email.html:103 #, python-format msgid "best regards,
The %(project_name)s team" -msgstr "Cordiali saluti,
Il team di %(project_name)s" +msgstr "Cordiali saluti,
il team %(project_name)s" #: vibes_auth/templates/user_reset_password_email.html:109 #: vibes_auth/templates/user_verification_email.html:108 @@ -393,12 +401,12 @@ msgstr "" #: vibes_auth/templates/user_verification_email.html:102 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Cordiali saluti,
il team di %(project_name)s" +msgstr "Cordiali saluti,
il team %(project_name)s" #: vibes_auth/utils/emailing.py:27 #, python-brace-format msgid "{config.PROJECT_NAME} | Activate Account" -msgstr "{config.PROJECT_NAME} | Attivare l'account" +msgstr "{config.PROJECT_NAME} | Attiva l'account" #: vibes_auth/utils/emailing.py:69 #, python-brace-format @@ -413,17 +421,14 @@ msgstr "" "Formato del numero di telefono non valido. Il numero deve essere inserito " "nel formato: \"+999999999\". Sono consentite fino a 15 cifre." -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "Il token non è valido" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "La password è stata reimpostata con successo!" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "Avete già attivato l'account..." - -#~ msgid "eVibes Auth" -#~ msgstr "Autorizzazione eVibes" diff --git a/vibes_auth/locale/ja_JP/LC_MESSAGES/django.mo b/vibes_auth/locale/ja_JP/LC_MESSAGES/django.mo index 36220521..429ef994 100644 Binary files a/vibes_auth/locale/ja_JP/LC_MESSAGES/django.mo and b/vibes_auth/locale/ja_JP/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/ja_JP/LC_MESSAGES/django.po b/vibes_auth/locale/ja_JP/LC_MESSAGES/django.po index a2bd3865..3e02d0e4 100644 --- a/vibes_auth/locale/ja_JP/LC_MESSAGES/django.po +++ b/vibes_auth/locale/ja_JP/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "バランス" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "オーダー" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "受注状況" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "個人情報" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "アクセス許可" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "重要な日程" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "追加情報" @@ -70,7 +70,7 @@ msgstr "トークンの検証" msgid "Verify a token (refresh or access)." msgstr "トークンを確認する(リフレッシュまたはアクセス)。" -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "トークンは有効です" @@ -103,7 +103,7 @@ msgid "confirm a user's password reset" msgstr "ユーザーのパスワード・リセットを確認する" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "パスワードが一致しない" @@ -113,9 +113,7 @@ msgstr "ユーザーアカウントの有効化" #: vibes_auth/docs/drf/viewsets.py:66 msgid "activation link is invalid or account already activated" -msgstr "" -"アクティベーションリンクが無効であるか、アカウントがすでにアクティベーション" -"されています。" +msgstr "アクティベーションリンクが無効であるか、アカウントがすでにアクティベーションされています。" #: vibes_auth/docs/drf/viewsets.py:71 msgid "merge client-stored recently viewed products" @@ -132,7 +130,7 @@ msgstr "パスワードが弱すぎる" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name}が存在しません:{uuid}" +msgstr "{name}は存在しません:{uuid}が存在しません!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -141,15 +139,15 @@ msgstr "不正な電子メール" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "不正な電話番号:{phone_number}。" +msgstr "電話番号が不正です:{phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "無効な属性形式です:{attribute_pair}。" +msgstr "無効な属性形式です:{attribute_pair}です!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "アクティベーションリンクが無効です!" @@ -161,17 +159,17 @@ msgstr "アカウントはすでに有効になっています..." msgid "something went wrong: {e!s}" msgstr "何かが間違っていた:{e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "トークンが無効です!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "このユーザーが最近閲覧した商品(最大48件)を逆順に表示します。" -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "グループ" @@ -179,7 +177,7 @@ msgstr "グループ" msgid "wishlist" msgstr "ウィッシュリスト" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "アバター" @@ -190,113 +188,122 @@ msgstr "属性は、カスタム・データを保存するために使用する #: vibes_auth/graphene/object_types.py:49 #, python-brace-format msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" -msgstr "言語は{LANGUAGES}のいずれかで、デフォルトは{LANGUAGE_CODE}です。" +msgstr "言語は {LANGUAGES} のいずれかで、デフォルトは {LANGUAGE_CODE} です。" -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "住所" + +#: vibes_auth/models.py:85 msgid "email" msgstr "電子メール" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "ユーザーのメールアドレス" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "電話番号" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "ユーザー電話番号" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "名前" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "姓" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "ユーザープロフィール画像" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "確認済み" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "ユーザーの認証状況" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "アクティブ" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "アカウントを削除する代わりに、この選択を解除する" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "購読中" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "ユーザーのニュースレター購読状況" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "アクティベーション・トークン" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "属性" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "ユーザー" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "ユーザー" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "グループ" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "卓越したトークン" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "トークン残高" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "ブラックリストトークン" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "ブラックリストに載ったトークン" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "アクティブなアカウントが見つかりません" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "クラスにtoken_class属性を設定する必要があります!" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "トークンのブラックリスト入り" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "無効なトークン" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "トークンにユーザー uuid クレームが存在しない" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "ユーザーが存在しない" @@ -317,16 +324,13 @@ msgstr "パスワード再設定確認" #: vibes_auth/templates/user_verification_email.html:91 #, python-format msgid "hello %(user_first_name)s," -msgstr "こんにちは、%(user_first_name)sです、" +msgstr "こんにちは %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" -msgstr "" -"パスワードの再設定依頼が届いております。以下のボタンをクリックして、パスワー" -"ドをリセットしてください:" +msgstr "パスワードの再設定依頼が届いております。以下のボタンをクリックして、パスワードをリセットしてください:" #: vibes_auth/templates/user_reset_password_email.html:95 msgid "" @@ -342,8 +346,7 @@ msgid "" "if the button above does not work, please copy and paste the following URL\n" " into your web browser:" msgstr "" -"上記のボタンが機能しない場合は、次のURLをコピーしてウェブブラウザに貼り付けて" -"ください。\n" +"上記のボタンが機能しない場合は、次のURLをコピーしてウェブブラウザに貼り付けてください。\n" " をウェブブラウザに貼り付けてください:" #: vibes_auth/templates/user_reset_password_email.html:101 @@ -357,7 +360,7 @@ msgstr "" #: vibes_auth/templates/user_reset_password_email.html:103 #, python-format msgid "best regards,
The %(project_name)s team" -msgstr "よろしくお願いします、
%(project_name)sのチーム" +msgstr "よろしくお願いします、
%(project_name)sチーム" #: vibes_auth/templates/user_reset_password_email.html:109 #: vibes_auth/templates/user_verification_email.html:108 @@ -374,9 +377,7 @@ msgstr "アカウントの有効化" msgid "" "thank you for signing up for %(project_name)s. please activate your account\n" " by clicking the button below:" -msgstr "" -"%(project_name)sにご登録いただきありがとうございます。下のボタンをクリックし" -"てアカウントを有効にしてください:" +msgstr "%(project_name)sにご登録いただきありがとうございます。下のボタンをクリックしてアカウントを有効にしてください:" #: vibes_auth/templates/user_verification_email.html:96 msgid "" @@ -389,37 +390,32 @@ msgstr "" #: vibes_auth/templates/user_verification_email.html:102 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "よろしくお願いします、
%(project_name)sのチーム。" +msgstr "よろしくお願いします、
%(project_name)sチーム" #: vibes_auth/utils/emailing.py:27 #, python-brace-format msgid "{config.PROJECT_NAME} | Activate Account" -msgstr "{config.PROJECT_NAME}|アカウントの有効化| アカウントの有効化" +msgstr "{config.PROJECT_NAME}| アカウントの有効化| アカウントの有効化" #: vibes_auth/utils/emailing.py:69 #, python-brace-format msgid "{config.PROJECT_NAME} | Reset Password" -msgstr "{config.PROJECT_NAME}。| パスワードのリセット" +msgstr "{config.PROJECT_NAME} | パスワードのリセット" #: vibes_auth/validators.py:13 msgid "" "invalid phone number format. the number must be entered in the format: " "\"+999999999\". up to 15 digits allowed." -msgstr "" -"電話番号の形式が無効です。電話番号は次の形式で入力してください:" -"\"+999999999\".15桁まで入力可能です。" +msgstr "電話番号の形式が無効です。電話番号は次の形式で入力してください:\"+999999999\".15桁まで入力可能です。" -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "トークンが無効" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "パスワードのリセットに成功しました!" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "あなたはすでにアカウントを有効にしています..." - -#~ msgid "eVibes Auth" -#~ msgstr "eVibes Auth" diff --git a/vibes_auth/locale/kk_KZ/LC_MESSAGES/django.mo b/vibes_auth/locale/kk_KZ/LC_MESSAGES/django.mo index 0fc354f2..47c1f925 100644 Binary files a/vibes_auth/locale/kk_KZ/LC_MESSAGES/django.mo and b/vibes_auth/locale/kk_KZ/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/kk_KZ/LC_MESSAGES/django.po b/vibes_auth/locale/kk_KZ/LC_MESSAGES/django.po index bb8f1f37..8f4f37a3 100644 --- a/vibes_auth/locale/kk_KZ/LC_MESSAGES/django.po +++ b/vibes_auth/locale/kk_KZ/LC_MESSAGES/django.po @@ -5,9 +5,9 @@ # msgid "" msgstr "" -"Project-Id-Version: EVIBES 2.8.10\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-06-16 08:59+0100\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: LANGUAGE \n" @@ -21,27 +21,27 @@ msgstr "" msgid "balance" msgstr "" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "" @@ -73,7 +73,7 @@ msgstr "" msgid "Verify a token (refresh or access)." msgstr "" -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "" @@ -106,7 +106,7 @@ msgid "confirm a user's password reset" msgstr "" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "" @@ -149,8 +149,8 @@ msgstr "" msgid "Invalid attribute format: {attribute_pair}" msgstr "" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "" @@ -162,7 +162,7 @@ msgstr "" msgid "something went wrong: {e!s}" msgstr "" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "" @@ -172,7 +172,7 @@ msgid "" "chronological order" msgstr "" -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "" @@ -180,7 +180,7 @@ msgstr "" msgid "wishlist" msgstr "" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "" @@ -193,111 +193,120 @@ msgstr "" msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" msgstr "" -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "" + +#: vibes_auth/models.py:85 msgid "email" msgstr "" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "" @@ -395,14 +404,14 @@ msgid "" "\"+999999999\". up to 15 digits allowed." msgstr "" -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "" diff --git a/vibes_auth/locale/nl_NL/LC_MESSAGES/django.mo b/vibes_auth/locale/nl_NL/LC_MESSAGES/django.mo index 449d81f4..e1782390 100644 Binary files a/vibes_auth/locale/nl_NL/LC_MESSAGES/django.mo and b/vibes_auth/locale/nl_NL/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/nl_NL/LC_MESSAGES/django.po b/vibes_auth/locale/nl_NL/LC_MESSAGES/django.po index 008ca5c8..737b2e82 100644 --- a/vibes_auth/locale/nl_NL/LC_MESSAGES/django.po +++ b/vibes_auth/locale/nl_NL/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "Saldo" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "Bestel" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "Bestellingen" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "Persoonlijke info" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "Rechten" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "Belangrijke data" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "Extra info" @@ -70,7 +70,7 @@ msgstr "Een token verifiëren" msgid "Verify a token (refresh or access)." msgstr "Een token verifiëren (verversen of toegang)." -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "The token is valid" @@ -105,7 +105,7 @@ msgid "confirm a user's password reset" msgstr "Bevestig het resetten van het wachtwoord van een gebruiker" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "Wachtwoorden komen niet overeen" @@ -134,7 +134,7 @@ msgstr "Het wachtwoord is te zwak" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} bestaat niet: {uuid}" +msgstr "{name} bestaat niet: {uuid}!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -143,15 +143,15 @@ msgstr "Misvormde e-mail" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "Misvormd telefoonnummer: {phone_number}" +msgstr "Misvormd telefoonnummer: {phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "Ongeldig attribuutformaat: {attribute_pair}" +msgstr "Ongeldig attribuutformaat: {attribute_pair}!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "Activeringslink is ongeldig!" @@ -163,19 +163,19 @@ msgstr "Account is al geactiveerd..." msgid "something went wrong: {e!s}" msgstr "Er ging iets mis: {e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "Token is invalid!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "" "De producten die deze gebruiker het laatst heeft bekeken (max 48), in " "omgekeerd-chronologische volgorde." -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "Groepen" @@ -183,7 +183,7 @@ msgstr "Groepen" msgid "wishlist" msgstr "Verlanglijst" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "Avatar" @@ -196,111 +196,120 @@ msgstr "Attributen kunnen worden gebruikt om aangepaste gegevens op te slaan" msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" msgstr "Taal is een van de {LANGUAGES} met standaard {LANGUAGE_CODE}" -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "Adressen" + +#: vibes_auth/models.py:85 msgid "email" msgstr "E-mail" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "E-mailadres gebruiker" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "Telefoonnummer" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "Telefoonnummer gebruiker" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "Voornaam" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "Achternaam" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "Afbeelding gebruikersprofiel" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "Is geverifieerd" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "Verificatiestatus van de gebruiker" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "Is actief" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "Deselecteer dit in plaats van accounts te verwijderen" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "Is geabonneerd" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "Inschrijvingsstatus nieuwsbrief gebruiker" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "Activeringstoken" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "Attributen" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "Gebruiker" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "Gebruikers" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "Groep" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "Uitstekende penning" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "Uitstaande tokens" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "Token op zwarte lijst" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "Tokens op de zwarte lijst" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "Geen actieve account gevonden" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "Moet token_class attribuut instellen op klasse!" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "Token op zwarte lijst" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "Invalid token" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "Geen gebruiker uuid claim aanwezig in token" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "Gebruiker bestaat niet" @@ -325,12 +334,11 @@ msgstr "Hallo %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "" -"We hebben een verzoek ontvangen om je wachtwoord opnieuw in te stellen. Klik " -"op de knop hieronder om je wachtwoord opnieuw in te stellen:" +"We hebben een verzoek ontvangen om je wachtwoord opnieuw in te stellen. Klik" +" op de knop hieronder om je wachtwoord opnieuw in te stellen:" #: vibes_auth/templates/user_reset_password_email.html:95 msgid "" @@ -360,7 +368,7 @@ msgstr "" #: vibes_auth/templates/user_reset_password_email.html:103 #, python-format msgid "best regards,
The %(project_name)s team" -msgstr "Vriendelijke groeten,
Het %(project_name)s-team" +msgstr "Vriendelijke groeten,
Het %(project_name)s team" #: vibes_auth/templates/user_reset_password_email.html:109 #: vibes_auth/templates/user_verification_email.html:108 @@ -378,8 +386,8 @@ msgid "" "thank you for signing up for %(project_name)s. please activate your account\n" " by clicking the button below:" msgstr "" -"Bedankt voor het aanmelden bij %(project_name)s. Activeer je account door op " -"de onderstaande knop te klikken:" +"Bedankt voor het aanmelden bij %(project_name)s. Activeer je account door op" +" de onderstaande knop te klikken:" #: vibes_auth/templates/user_verification_email.html:96 msgid "" @@ -392,17 +400,17 @@ msgstr "" #: vibes_auth/templates/user_verification_email.html:102 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Vriendelijke groeten,
het %(project_name)s-team" +msgstr "Vriendelijke groeten,
het %(project_name)s team" #: vibes_auth/utils/emailing.py:27 #, python-brace-format msgid "{config.PROJECT_NAME} | Activate Account" -msgstr "{config.PROJECT_NAME}. | Account activeren" +msgstr "{config.PROJECT_NAME} | Account activeren" #: vibes_auth/utils/emailing.py:69 #, python-brace-format msgid "{config.PROJECT_NAME} | Reset Password" -msgstr "{config.PROJECT_NAME}. | Wachtwoord opnieuw instellen" +msgstr "{config.PROJECT_NAME} | Wachtwoord opnieuw instellen" #: vibes_auth/validators.py:13 msgid "" @@ -412,17 +420,14 @@ msgstr "" "Ongeldig formaat telefoonnummer. Het nummer moet worden ingevoerd in de " "indeling: \"+999999999\". Maximaal 15 cijfers toegestaan." -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "Het token is ongeldig" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "Wachtwoord is succesvol gereset!" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "Je hebt de account al geactiveerd..." - -#~ msgid "eVibes Auth" -#~ msgstr "eVibes Auth" diff --git a/vibes_auth/locale/pl_PL/LC_MESSAGES/django.mo b/vibes_auth/locale/pl_PL/LC_MESSAGES/django.mo index dd7ecfac..3bda44e3 100644 Binary files a/vibes_auth/locale/pl_PL/LC_MESSAGES/django.mo and b/vibes_auth/locale/pl_PL/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/pl_PL/LC_MESSAGES/django.po b/vibes_auth/locale/pl_PL/LC_MESSAGES/django.po index fb1a818a..7a658933 100644 --- a/vibes_auth/locale/pl_PL/LC_MESSAGES/django.po +++ b/vibes_auth/locale/pl_PL/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "Równowaga" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "Zamówienie" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "Zamówienia" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "Informacje osobiste" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "Uprawnienia" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "Ważne daty" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "Dodatkowe informacje" @@ -52,7 +52,8 @@ msgstr "Uzyskanie pary tokenów" #: vibes_auth/docs/drf/views.py:16 msgid "obtain a token pair (refresh and access) for authentication." -msgstr "Uzyskanie pary tokenów (odświeżenie i dostęp) w celu uwierzytelnienia." +msgstr "" +"Uzyskanie pary tokenów (odświeżenie i dostęp) w celu uwierzytelnienia." #: vibes_auth/docs/drf/views.py:35 msgid "refresh a token pair" @@ -70,7 +71,7 @@ msgstr "Weryfikacja tokena" msgid "Verify a token (refresh or access)." msgstr "Weryfikacja tokena (odświeżenie lub dostęp)." -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "Token jest ważny" @@ -105,7 +106,7 @@ msgid "confirm a user's password reset" msgstr "Potwierdzenie zresetowania hasła użytkownika" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "Hasła nie są zgodne" @@ -134,7 +135,7 @@ msgstr "Hasło jest zbyt słabe" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} nie istnieje: {uuid}" +msgstr "{name} nie istnieje: {uuid}!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -143,15 +144,15 @@ msgstr "Zniekształcona wiadomość e-mail" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "Zniekształcony numer telefonu: {phone_number}" +msgstr "Zniekształcony numer telefonu: {phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "Nieprawidłowy format atrybutu: {attribute_pair}" +msgstr "Nieprawidłowy format atrybutu: {attribute_pair}!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "Link aktywacyjny jest nieprawidłowy!" @@ -163,19 +164,19 @@ msgstr "Konto zostało już aktywowane..." msgid "something went wrong: {e!s}" msgstr "Coś poszło nie tak: {e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "Token jest nieprawidłowy!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "" "Produkty ostatnio przeglądane przez tego użytkownika (maks. 48), w " "kolejności odwrotnej do chronologicznej." -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "Grupy" @@ -183,7 +184,7 @@ msgstr "Grupy" msgid "wishlist" msgstr "Lista życzeń" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "Awatar" @@ -196,111 +197,120 @@ msgstr "Atrybuty mogą być używane do przechowywania niestandardowych danych" msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" msgstr "Język jest jednym z {LANGUAGES} z domyślnym {LANGUAGE_CODE}." -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "Adresy" + +#: vibes_auth/models.py:85 msgid "email" msgstr "E-mail" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "Adres e-mail użytkownika" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "Numer telefonu" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "Numer telefonu użytkownika" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "Imię" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "Nazwisko" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "Obraz profilu użytkownika" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "Czy zweryfikowano" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "Status weryfikacji użytkownika" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "Jest aktywny" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "Odznacz to zamiast usuwać konta" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "Jest subskrybowany" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "Status subskrypcji newslettera użytkownika" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "Token aktywacyjny" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "Atrybuty" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "Użytkownik" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "Użytkownicy" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "Grupa" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "Wyjątkowy token" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "Zaległe tokeny" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "Token na czarnej liście" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "Tokeny znajdujące się na czarnej liście" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "Nie znaleziono aktywnego konta" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "Należy ustawić atrybut token_class na klasie!" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "Token na czarnej liście" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "Nieprawidłowy token" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "Brak oświadczenia uuid użytkownika w tokenie" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "Użytkownik nie istnieje" @@ -325,8 +335,7 @@ msgstr "Witaj %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "" "Otrzymaliśmy prośbę o zresetowanie hasła. Zresetuj hasło, klikając poniższy " @@ -392,7 +401,7 @@ msgstr "" #: vibes_auth/templates/user_verification_email.html:102 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Z wyrazami szacunku,
zespół %(project_name)s" +msgstr "Najlepsze pozdrowienia,
zespół %(project_name)s" #: vibes_auth/utils/emailing.py:27 #, python-brace-format @@ -409,20 +418,17 @@ msgid "" "invalid phone number format. the number must be entered in the format: " "\"+999999999\". up to 15 digits allowed." msgstr "" -"Nieprawidłowy format numeru telefonu. Numer musi być wprowadzony w formacie: " -"\"+999999999\". Dozwolone do 15 cyfr." +"Nieprawidłowy format numeru telefonu. Numer musi być wprowadzony w formacie:" +" \"+999999999\". Dozwolone do 15 cyfr." -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "Token jest nieprawidłowy" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "Hasło zostało pomyślnie zresetowane!" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "Konto zostało już aktywowane..." - -#~ msgid "eVibes Auth" -#~ msgstr "eVibes Auth" diff --git a/vibes_auth/locale/pt_BR/LC_MESSAGES/django.mo b/vibes_auth/locale/pt_BR/LC_MESSAGES/django.mo index 8e121b4e..367a980b 100644 Binary files a/vibes_auth/locale/pt_BR/LC_MESSAGES/django.mo and b/vibes_auth/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/pt_BR/LC_MESSAGES/django.po b/vibes_auth/locale/pt_BR/LC_MESSAGES/django.po index a1cd0796..0ae31ec7 100644 --- a/vibes_auth/locale/pt_BR/LC_MESSAGES/django.po +++ b/vibes_auth/locale/pt_BR/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "Equilíbrio" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "Pedido" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "Pedidos" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "Informações pessoais" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "Permissões" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "Datas importantes" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "Informações adicionais" @@ -70,7 +70,7 @@ msgstr "Verificar um token" msgid "Verify a token (refresh or access)." msgstr "Verificar um token (atualização ou acesso)." -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "O token é válido" @@ -104,7 +104,7 @@ msgid "confirm a user's password reset" msgstr "Confirmar a redefinição de senha de um usuário" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "As senhas não correspondem" @@ -131,7 +131,7 @@ msgstr "A senha é muito fraca" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} não existe: {uuid}" +msgstr "{name} não existe: {uuid}!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -140,15 +140,15 @@ msgstr "E-mail malformado" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "Número de telefone malformado: {phone_number}" +msgstr "Número de telefone malformado: {phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "Formato de atributo inválido: {attribute_pair}" +msgstr "Formato de atributo inválido: {attribute_pair}!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "O link de ativação é inválido!" @@ -160,19 +160,19 @@ msgstr "A conta já foi ativada..." msgid "something went wrong: {e!s}" msgstr "Algo deu errado: {e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "O token é inválido!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "" -"Os produtos que esse usuário visualizou mais recentemente (máximo de 48), em " -"ordem cronológica inversa." +"Os produtos que esse usuário visualizou mais recentemente (máximo de 48), em" +" ordem cronológica inversa." -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "Grupos" @@ -180,7 +180,7 @@ msgstr "Grupos" msgid "wishlist" msgstr "Lista de desejos" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "Avatar" @@ -193,111 +193,120 @@ msgstr "Os atributos podem ser usados para armazenar dados personalizados" msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" msgstr "O idioma é um dos {LANGUAGES} com o padrão {LANGUAGE_CODE}" -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "Endereços" + +#: vibes_auth/models.py:85 msgid "email" msgstr "E-mail" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "Endereço de e-mail do usuário" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "Número de telefone" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "Número de telefone do usuário" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "Primeiro nome" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "Sobrenome" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "Imagem do perfil do usuário" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "É verificado" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "Status de verificação do usuário" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "Está ativo" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "Desmarque essa opção em vez de excluir contas" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "Está inscrito" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "Status da assinatura do boletim informativo do usuário" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "Token de ativação" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "Atributos" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "Usuário" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "Usuários" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "Grupo" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "Token excepcional" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "Tokens pendentes" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "Token na lista negra" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "Tokens na lista negra" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "Nenhuma conta ativa encontrada" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "É necessário definir o atributo token_class na classe!" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "Token na lista negra" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "Token inválido" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "Nenhuma reivindicação de uuid de usuário presente no token" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "O usuário não existe" @@ -322,8 +331,7 @@ msgstr "Olá %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "" "Recebemos uma solicitação para redefinir sua senha. Para redefinir sua " @@ -357,7 +365,7 @@ msgstr "" #: vibes_auth/templates/user_reset_password_email.html:103 #, python-format msgid "best regards,
The %(project_name)s team" -msgstr "Atenciosamente,
A equipe de %(project_name)s" +msgstr "Atenciosamente,
A equipe %(project_name)s" #: vibes_auth/templates/user_reset_password_email.html:109 #: vibes_auth/templates/user_verification_email.html:108 @@ -389,7 +397,7 @@ msgstr "" #: vibes_auth/templates/user_verification_email.html:102 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "Atenciosamente,
a equipe de %(project_name)s" +msgstr "Atenciosamente,
a equipe %(project_name)s" #: vibes_auth/utils/emailing.py:27 #, python-brace-format @@ -409,17 +417,14 @@ msgstr "" "Formato de número telefônico inválido. O número deve ser inserido no " "formato: \"+999999999\". São permitidos até 15 dígitos." -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "O token é inválido" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "A senha foi redefinida com sucesso!" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "Você já ativou a conta..." - -#~ msgid "eVibes Auth" -#~ msgstr "Autenticação eVibes" diff --git a/vibes_auth/locale/ro_RO/LC_MESSAGES/django.mo b/vibes_auth/locale/ro_RO/LC_MESSAGES/django.mo index 434747fb..f25e4286 100644 Binary files a/vibes_auth/locale/ro_RO/LC_MESSAGES/django.mo and b/vibes_auth/locale/ro_RO/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/ro_RO/LC_MESSAGES/django.po b/vibes_auth/locale/ro_RO/LC_MESSAGES/django.po index b28bed23..8786c612 100644 --- a/vibes_auth/locale/ro_RO/LC_MESSAGES/django.po +++ b/vibes_auth/locale/ro_RO/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "Echilibru" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "Comandă" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "Ordine" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "Informații personale" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "Permisiuni" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "Date importante" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "Informații suplimentare" @@ -71,7 +71,7 @@ msgstr "Verificarea unui jeton" msgid "Verify a token (refresh or access)." msgstr "Verificarea unui jeton (reîmprospătare sau acces)." -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "Jetonul este valid" @@ -106,7 +106,7 @@ msgid "confirm a user's password reset" msgstr "Confirmați resetarea parolei unui utilizator" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "Parolele nu se potrivesc" @@ -134,7 +134,7 @@ msgstr "Parola este prea slabă" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} nu există: {uuid}" +msgstr "{name} nu există: {uuid}!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -143,15 +143,15 @@ msgstr "E-mail malformat" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "Număr de telefon malformat: {phone_number}" +msgstr "Număr de telefon malformat: {phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "Format de atribut invalid: {attribute_pair}" +msgstr "Format de atribut invalid: {attribute_pair}!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "Linkul de activare este invalid!" @@ -163,19 +163,19 @@ msgstr "Contul a fost deja activat..." msgid "something went wrong: {e!s}" msgstr "Ceva nu a mers bine: {e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "Token-ul nu este valabil!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "" "Produsele pe care acest utilizator le-a vizualizat cel mai recent (max 48), " "în ordine cronologică inversă." -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "Grupuri" @@ -183,7 +183,7 @@ msgstr "Grupuri" msgid "wishlist" msgstr "Lista dorințelor" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "Avatar" @@ -194,113 +194,122 @@ msgstr "Atributele pot fi utilizate pentru a stoca date personalizate" #: vibes_auth/graphene/object_types.py:49 #, python-brace-format msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" -msgstr "Limba este una dintre {LANGUAGES} cu {LANGUAGE_CODE} implicit" +msgstr "Limba este una dintre {LANGUAGES} cu implicit {LANGUAGE_CODE}" -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "Adrese" + +#: vibes_auth/models.py:85 msgid "email" msgstr "E-mail" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "Adresa de e-mail a utilizatorului" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "Număr de telefon" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "Numărul de telefon al utilizatorului" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "Numele și prenumele" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "Numele de familie" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "Imagine profil utilizator" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "Este verificat" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "Statutul de verificare al utilizatorului" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "Este activ" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "Deselectați acest lucru în loc să ștergeți conturile" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "Este abonat" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "Starea abonării utilizatorului la buletinul informativ" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "Jeton de activare" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "Atribute" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "Utilizator" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "Utilizatori" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "Grup" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "Simbol excepțional" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "Jetoane restante" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "Token pe lista neagră" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "Jetoane pe lista neagră" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "Nu s-a găsit niciun cont activ" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "Trebuie să setați atributul token_class pe clasă!" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "Token pe lista neagră" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "Jeton invalid" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "În jeton nu este prezentă nicio cerere uuid a utilizatorului" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "Utilizatorul nu există" @@ -325,8 +334,7 @@ msgstr "Bună ziua %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "" "Am primit o cerere de resetare a parolei dumneavoastră. Vă rugăm să vă " @@ -346,8 +354,7 @@ msgid "" "if the button above does not work, please copy and paste the following URL\n" " into your web browser:" msgstr "" -"Dacă butonul de mai sus nu funcționează, vă rugăm să copiați și să lipiți " -"următoarea adresă URL\n" +"Dacă butonul de mai sus nu funcționează, vă rugăm să copiați și să lipiți următoarea adresă URL\n" " în browserul dvs. web:" #: vibes_auth/templates/user_reset_password_email.html:101 @@ -413,17 +420,14 @@ msgstr "" "Format invalid al numărului de telefon. Numărul trebuie să fie introdus în " "formatul: \"+999999999\". Sunt permise până la 15 cifre." -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "Jetonul nu este valabil" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "Parola a fost resetată cu succes!" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "Ați activat deja contul..." - -#~ msgid "eVibes Auth" -#~ msgstr "eVibes Auth" diff --git a/vibes_auth/locale/ru_RU/LC_MESSAGES/django.mo b/vibes_auth/locale/ru_RU/LC_MESSAGES/django.mo index 1661d369..af290bd2 100644 Binary files a/vibes_auth/locale/ru_RU/LC_MESSAGES/django.mo and b/vibes_auth/locale/ru_RU/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/ru_RU/LC_MESSAGES/django.po b/vibes_auth/locale/ru_RU/LC_MESSAGES/django.po index b5400313..64629900 100644 --- a/vibes_auth/locale/ru_RU/LC_MESSAGES/django.po +++ b/vibes_auth/locale/ru_RU/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "Баланс" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "Заказать" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "Заказы" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "Личная информация" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "Разрешения" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "Важные даты" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "Дополнительная информация" @@ -48,29 +48,29 @@ msgstr "Аутентификация" #: vibes_auth/docs/drf/views.py:15 msgid "obtain a token pair" -msgstr "Получение пары маркеров" +msgstr "Получение пары токенов" #: vibes_auth/docs/drf/views.py:16 msgid "obtain a token pair (refresh and access) for authentication." -msgstr "Получите пару маркеров (refresh и access) для аутентификации." +msgstr "Получите пару токенов (refresh и access) для аутентификации." #: vibes_auth/docs/drf/views.py:35 msgid "refresh a token pair" -msgstr "Обновить пару маркеров" +msgstr "Обновить пару токенов" #: vibes_auth/docs/drf/views.py:36 msgid "refresh a token pair (refresh and access)." -msgstr "Обновление пары маркеров (обновление и доступ)." +msgstr "Обновление пары токенов (обновление и доступ)." #: vibes_auth/docs/drf/views.py:55 msgid "verify a token" -msgstr "Проверка маркера" +msgstr "Проверка токена" #: vibes_auth/docs/drf/views.py:56 msgid "Verify a token (refresh or access)." -msgstr "Проверка маркера (обновление или доступ)." +msgstr "Проверка токена (обновление или доступ)." -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "Токен действителен" @@ -105,7 +105,7 @@ msgid "confirm a user's password reset" msgstr "Подтверждение сброса пароля пользователя" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "Пароли не совпадают" @@ -119,7 +119,8 @@ msgstr "Ссылка на активацию недействительна ил #: vibes_auth/docs/drf/viewsets.py:71 msgid "merge client-stored recently viewed products" -msgstr "Объедините недавно просмотренные продукты, хранящиеся в памяти клиента" +msgstr "" +"Объедините недавно просмотренные продукты, хранящиеся в памяти клиента" #: vibes_auth/graphene/mutations.py:41 msgid "the user's b64-encoded uuid who referred the new user to us." @@ -134,7 +135,7 @@ msgstr "Пароль слишком слабый" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} не существует: {uuid}" +msgstr "{name} не существует: {uuid}!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -143,15 +144,15 @@ msgstr "Некорректное письмо" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "Некорректный номер телефона: {phone_number}" +msgstr "Некорректный номер телефона: {phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "Недопустимый формат атрибута: {attribute_pair}" +msgstr "Недопустимый формат атрибута: {attribute_pair}!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "Ссылка на активацию недействительна!" @@ -163,19 +164,19 @@ msgstr "Аккаунт уже активирован..." msgid "something went wrong: {e!s}" msgstr "Что-то пошло не так: {e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "Токен недействителен!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "" -"Продукты, которые этот пользователь просматривал в последнее время (не более " -"48), в обратном хронологическом порядке." +"Продукты, которые этот пользователь просматривал в последнее время (не более" +" 48), в обратном хронологическом порядке." -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "Группы" @@ -183,7 +184,7 @@ msgstr "Группы" msgid "wishlist" msgstr "Список желаний" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "Аватар" @@ -196,111 +197,120 @@ msgstr "Атрибуты могут использоваться для хран msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" msgstr "Язык - один из {LANGUAGES}, по умолчанию {LANGUAGE_CODE}." -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "Адреса" + +#: vibes_auth/models.py:85 msgid "email" msgstr "Электронная почта" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "Адрес электронной почты пользователя" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "Номер телефона" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "Номер телефона пользователя" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "Имя" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "Фамилия" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "Изображение профиля пользователя" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "Проверено" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "Статус верификации пользователя" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "Активен" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "Снимите этот флажок вместо удаления учетных записей" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "Подписан" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "Статус подписки пользователя на рассылку новостей" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" -msgstr "Активационный маркер" +msgstr "Активационный токен" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "Атрибуты" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "Пользователь" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "Пользователи" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "Группа" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "Выдающийся жетон" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" -msgstr "Выпущенные жетоны" +msgstr "Выпущенные токены" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "Токен в черном списке" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" -msgstr "Токены, внесенные в черный список" +msgstr "Чёрный список токенов" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "Активная учетная запись не найдена" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "Необходимо установить атрибут token_class для класса!" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "Токен занесен в черный список" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "Неверный токен" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "В токене отсутствует утверждение uuid пользователя" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "Пользователь не существует" @@ -321,12 +331,11 @@ msgstr "Подтверждение сброса пароля" #: vibes_auth/templates/user_verification_email.html:91 #, python-format msgid "hello %(user_first_name)s," -msgstr "Здравствуйте, %(user_first_name)s," +msgstr "Привет %(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "" "Мы получили запрос на сброс вашего пароля. Пожалуйста, сбросьте пароль, " @@ -346,8 +355,7 @@ msgid "" "if the button above does not work, please copy and paste the following URL\n" " into your web browser:" msgstr "" -"Если кнопка выше не работает, пожалуйста, скопируйте и вставьте следующий " -"URL-адрес\n" +"Если кнопка выше не работает, пожалуйста, скопируйте и вставьте следующий URL-адрес\n" " в свой веб-браузер:" #: vibes_auth/templates/user_reset_password_email.html:101 @@ -360,7 +368,7 @@ msgstr "" #: vibes_auth/templates/user_reset_password_email.html:103 #, python-format msgid "best regards,
The %(project_name)s team" -msgstr "С наилучшими пожеланиями,
Команда %(project_name)s" +msgstr "С наилучшими пожеланиями,
Команда %(project_name)s" #: vibes_auth/templates/user_reset_password_email.html:109 #: vibes_auth/templates/user_verification_email.html:108 @@ -412,17 +420,14 @@ msgstr "" "Неверный формат телефонного номера. Номер должен быть введен в формате: " "\"+999999999\". Допускается до 15 цифр." -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "Токен недействителен" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "Пароль был успешно сброшен!" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "Вы уже активировали учетную запись..." - -#~ msgid "eVibes Auth" -#~ msgstr "eVibes Auth" diff --git a/vibes_auth/locale/zh_Hans/LC_MESSAGES/django.mo b/vibes_auth/locale/zh_Hans/LC_MESSAGES/django.mo index d7c54350..ac696c90 100644 Binary files a/vibes_auth/locale/zh_Hans/LC_MESSAGES/django.mo and b/vibes_auth/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/vibes_auth/locale/zh_Hans/LC_MESSAGES/django.po b/vibes_auth/locale/zh_Hans/LC_MESSAGES/django.po index b7a5db41..fce92396 100644 --- a/vibes_auth/locale/zh_Hans/LC_MESSAGES/django.po +++ b/vibes_auth/locale/zh_Hans/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ # msgid "" msgstr "" -"Project-Id-Version: 1\n" +"Project-Id-Version: EVIBES 2.9.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-06-21 22:42+0100\n" +"POT-Creation-Date: 2025-07-14 15:36+0300\n" "PO-Revision-Date: 2025-01-30 03:27+0000\n" "Last-Translator: EGOR GORBUNOV \n" "Language-Team: BRITISH ENGLISH \n" @@ -18,27 +18,27 @@ msgstr "" msgid "balance" msgstr "平衡" -#: vibes_auth/admin.py:44 +#: vibes_auth/admin.py:45 msgid "order" msgstr "订购" -#: vibes_auth/admin.py:45 vibes_auth/graphene/object_types.py:44 +#: vibes_auth/admin.py:46 vibes_auth/graphene/object_types.py:44 msgid "orders" msgstr "订单" -#: vibes_auth/admin.py:54 +#: vibes_auth/admin.py:56 msgid "personal info" msgstr "个人信息" -#: vibes_auth/admin.py:58 vibes_auth/graphene/object_types.py:43 +#: vibes_auth/admin.py:60 vibes_auth/graphene/object_types.py:43 msgid "permissions" msgstr "权限" -#: vibes_auth/admin.py:71 +#: vibes_auth/admin.py:73 msgid "important dates" msgstr "重要日期" -#: vibes_auth/admin.py:72 +#: vibes_auth/admin.py:74 msgid "additional info" msgstr "其他信息" @@ -70,7 +70,7 @@ msgstr "验证令牌" msgid "Verify a token (refresh or access)." msgstr "验证令牌(刷新或访问)。" -#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:55 +#: vibes_auth/docs/drf/views.py:62 vibes_auth/views.py:115 msgid "the token is valid" msgstr "令牌有效" @@ -103,7 +103,7 @@ msgid "confirm a user's password reset" msgstr "确认用户密码重置" #: vibes_auth/docs/drf/viewsets.py:57 vibes_auth/graphene/mutations.py:307 -#: vibes_auth/viewsets.py:73 +#: vibes_auth/viewsets.py:114 msgid "passwords do not match" msgstr "密码不匹配" @@ -130,7 +130,7 @@ msgstr "密码太弱" #: vibes_auth/graphene/mutations.py:107 #, python-brace-format msgid "{name} does not exist: {uuid}" -msgstr "{name} 不存在:{uuid}" +msgstr "{name} 不存在:{uuid}!" #: vibes_auth/graphene/mutations.py:115 msgid "malformed email" @@ -139,15 +139,15 @@ msgstr "畸形电子邮件" #: vibes_auth/graphene/mutations.py:120 #, python-brace-format msgid "malformed phone number: {phone_number}" -msgstr "畸形电话号码: {phone_number}" +msgstr "畸形电话号码:{phone_number}!" #: vibes_auth/graphene/mutations.py:142 #, python-brace-format msgid "Invalid attribute format: {attribute_pair}" -msgstr "属性格式无效:{attribute_pair}" +msgstr "属性格式无效:{attribute_pair}!" -#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:116 -#: vibes_auth/viewsets.py:135 +#: vibes_auth/graphene/mutations.py:263 vibes_auth/viewsets.py:157 +#: vibes_auth/viewsets.py:176 msgid "activation link is invalid!" msgstr "激活链接无效!" @@ -159,17 +159,17 @@ msgstr "帐户已激活..." msgid "something went wrong: {e!s}" msgstr "出了问题:{e!s}" -#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:84 +#: vibes_auth/graphene/mutations.py:314 vibes_auth/viewsets.py:125 msgid "token is invalid!" msgstr "令牌无效!" #: vibes_auth/graphene/object_types.py:40 msgid "" -"the products this user has viewed most recently (max 48), in reverse‐" -"chronological order" +"the products this user has viewed most recently (max 48), in " +"reverse‐chronological order" msgstr "该用户最近查看过的产品(最多 48 个),按倒序排列。" -#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:117 +#: vibes_auth/graphene/object_types.py:42 vibes_auth/models.py:180 msgid "groups" msgstr "组别" @@ -177,7 +177,7 @@ msgstr "组别" msgid "wishlist" msgstr "愿望清单" -#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:53 +#: vibes_auth/graphene/object_types.py:47 vibes_auth/models.py:102 msgid "avatar" msgstr "阿凡达" @@ -190,111 +190,120 @@ msgstr "属性可用于存储自定义数据" msgid "language is one of the {LANGUAGES} with default {LANGUAGE_CODE}" msgstr "语言是{LANGUAGES}之一,默认为{LANGUAGE_CODE}。" -#: vibes_auth/models.py:36 +#: vibes_auth/graphene/object_types.py:50 +msgid "address set" +msgstr "地址" + +#: vibes_auth/models.py:85 msgid "email" msgstr "电子邮件" -#: vibes_auth/models.py:36 +#: vibes_auth/models.py:85 msgid "user email address" msgstr "用户电子邮件地址" -#: vibes_auth/models.py:38 +#: vibes_auth/models.py:87 msgid "phone_number" msgstr "电话号码" -#: vibes_auth/models.py:43 +#: vibes_auth/models.py:92 msgid "user phone number" msgstr "用户电话号码" -#: vibes_auth/models.py:49 +#: vibes_auth/models.py:98 msgid "first_name" msgstr "姓名" -#: vibes_auth/models.py:50 +#: vibes_auth/models.py:99 msgid "last_name" msgstr "姓氏" -#: vibes_auth/models.py:56 +#: vibes_auth/models.py:105 msgid "user profile image" msgstr "用户配置文件图像" -#: vibes_auth/models.py:61 +#: vibes_auth/models.py:110 msgid "is verified" msgstr "已核实" -#: vibes_auth/models.py:62 +#: vibes_auth/models.py:111 msgid "user verification status" msgstr "用户验证状态" -#: vibes_auth/models.py:65 +#: vibes_auth/models.py:114 msgid "is_active" msgstr "处于活动状态" -#: vibes_auth/models.py:67 +#: vibes_auth/models.py:116 msgid "unselect this instead of deleting accounts" msgstr "取消选择此选项,而不是删除账户" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "is_subscribed" msgstr "已订阅" -#: vibes_auth/models.py:70 +#: vibes_auth/models.py:119 msgid "user's newsletter subscription status" msgstr "用户的通讯订阅状态" -#: vibes_auth/models.py:73 +#: vibes_auth/models.py:122 msgid "activation token" msgstr "激活令牌" -#: vibes_auth/models.py:75 +#: vibes_auth/models.py:124 msgid "attributes" msgstr "属性" -#: vibes_auth/models.py:109 +#: vibes_auth/models.py:158 msgid "user" msgstr "用户" -#: vibes_auth/models.py:110 +#: vibes_auth/models.py:159 msgid "users" msgstr "用户" -#: vibes_auth/models.py:116 +#: vibes_auth/models.py:179 msgid "group" msgstr "组别" -#: vibes_auth/models.py:123 +#: vibes_auth/models.py:196 msgid "outstanding token" msgstr "出色的代币" -#: vibes_auth/models.py:124 +#: vibes_auth/models.py:197 msgid "outstanding tokens" msgstr "未兑代币" -#: vibes_auth/models.py:130 +#: vibes_auth/models.py:215 msgid "blacklisted token" msgstr "黑名单令牌" -#: vibes_auth/models.py:131 +#: vibes_auth/models.py:216 msgid "blacklisted tokens" msgstr "黑名单令牌" -#: vibes_auth/serializers.py:112 vibes_auth/serializers.py:134 +#: vibes_auth/serializers.py:110 vibes_auth/serializers.py:132 +#: vibes_auth/serializers.py:154 vibes_auth/serializers.py:166 msgid "no active account" msgstr "未找到活动账户" -#: vibes_auth/serializers.py:205 +#: vibes_auth/serializers.py:142 +msgid "must set token_class attribute on class." +msgstr "必须在类上设置 token_class 属性!" + +#: vibes_auth/serializers.py:214 msgid "token_blacklisted" msgstr "令牌被列入黑名单" -#: vibes_auth/serializers.py:210 +#: vibes_auth/serializers.py:219 msgid "invalid token" msgstr "无效令牌" -#: vibes_auth/serializers.py:216 +#: vibes_auth/serializers.py:225 msgid "no user uuid claim present in token" msgstr "令牌中没有用户 uuid 声明" -#: vibes_auth/serializers.py:218 +#: vibes_auth/serializers.py:227 msgid "user does not exist" msgstr "用户不存在" @@ -315,12 +324,11 @@ msgstr "密码重置确认" #: vibes_auth/templates/user_verification_email.html:91 #, python-format msgid "hello %(user_first_name)s," -msgstr "您好 %(user_first_name)s、" +msgstr "你好%(user_first_name)s," #: vibes_auth/templates/user_reset_password_email.html:92 msgid "" -"we have received a request to reset your password. please reset your " -"password\n" +"we have received a request to reset your password. please reset your password\n" " by clicking the button below:" msgstr "我们收到了重置密码的请求。请点击下面的按钮重置密码:" @@ -352,7 +360,7 @@ msgstr "" #: vibes_auth/templates/user_reset_password_email.html:103 #, python-format msgid "best regards,
The %(project_name)s team" -msgstr "致以最诚挚的问候,
%(project_name)s团队" +msgstr "致以最诚挚的问候,
%(project_name)s 团队" #: vibes_auth/templates/user_reset_password_email.html:109 #: vibes_auth/templates/user_verification_email.html:108 @@ -382,36 +390,32 @@ msgstr "" #: vibes_auth/templates/user_verification_email.html:102 #, python-format msgid "best regards,
the %(project_name)s team" -msgstr "致以最诚挚的问候,
%(project_name)s团队" +msgstr "致以最崇高的敬意,
%(project_name)s_团队" #: vibes_auth/utils/emailing.py:27 #, python-brace-format msgid "{config.PROJECT_NAME} | Activate Account" -msgstr "{config.PROJECT_NAME} | 激活账户| 激活账户" +msgstr "{config.PROJECT_NAME}| 激活帐户" #: vibes_auth/utils/emailing.py:69 #, python-brace-format msgid "{config.PROJECT_NAME} | Reset Password" -msgstr "{config.PROJECT_NAME} 重置密码| 重置密码" +msgstr "{config.PROJECT_NAME}| 重置密码" #: vibes_auth/validators.py:13 msgid "" "invalid phone number format. the number must be entered in the format: " "\"+999999999\". up to 15 digits allowed." -msgstr "" -"电话号码格式无效。电话号码必须按格式输入:\"+999999999\".最多允许 15 位数字。" +msgstr "电话号码格式无效。电话号码必须按格式输入:\"+999999999\".最多允许 15 位数字。" -#: vibes_auth/views.py:57 +#: vibes_auth/views.py:117 msgid "the token is invalid" msgstr "令牌无效" -#: vibes_auth/viewsets.py:88 +#: vibes_auth/viewsets.py:129 msgid "password reset successfully" msgstr "密码已重置成功!" -#: vibes_auth/viewsets.py:121 +#: vibes_auth/viewsets.py:162 msgid "account already activated!" msgstr "您已经激活了账户..." - -#~ msgid "eVibes Auth" -#~ msgstr "eVibes Auth" diff --git a/vibes_auth/managers.py b/vibes_auth/managers.py index 67a864c4..ebd2be9b 100644 --- a/vibes_auth/managers.py +++ b/vibes_auth/managers.py @@ -7,7 +7,7 @@ from django.contrib.auth.hashers import make_password from core.models import Address, Order -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") class UserManager(BaseUserManager): @@ -22,11 +22,12 @@ class UserManager(BaseUserManager): order.user = user order.save() orders.add(order.uuid) - for order in Order.objects.filter(attributes__icontains=user.phone_number): - if not order.user: - order.user = user - order.save() - orders.add(order.uuid) + if user.phone_number: + for order in Order.objects.filter(attributes__icontains=user.phone_number): + if not order.user: + order.user = user + order.save() + orders.add(order.uuid) for address in Address.objects.filter(billing_address_order__in=orders): if not address.user: address.user = user diff --git a/vibes_auth/migrations/0001_initial.py b/vibes_auth/migrations/0001_initial.py index e867215a..d0314d29 100644 --- a/vibes_auth/migrations/0001_initial.py +++ b/vibes_auth/migrations/0001_initial.py @@ -16,87 +16,179 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('auth', '0012_alter_user_first_name_max_length'), + ("auth", "0012_alter_user_first_name_max_length"), ] operations = [ migrations.CreateModel( - name='Group', - fields=[ - ], + name="Group", + fields=[], options={ - 'verbose_name': 'group', - 'verbose_name_plural': 'groups', - 'proxy': True, - 'indexes': [], - 'constraints': [], + "verbose_name": "group", + "verbose_name_plural": "groups", + "proxy": True, + "indexes": [], + "constraints": [], }, - bases=('auth.group',), + bases=("auth.group",), managers=[ - ('objects', django.contrib.auth.models.GroupManager()), + ("objects", django.contrib.auth.models.GroupManager()), ], ), migrations.CreateModel( - name='User', + name="User", fields=[ - ('password', models.CharField(max_length=128, verbose_name='password')), - ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), - ('is_superuser', models.BooleanField(default=False, - help_text='Designates that this user has all permissions without explicitly assigning them.', - verbose_name='superuser status')), - ('is_staff', models.BooleanField(default=False, - help_text='Designates whether the user can log into this admin site.', - verbose_name='staff status')), - ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, - help_text='unique id is used to surely identify any database object', - primary_key=True, serialize=False, verbose_name='unique id')), - ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, - help_text='when the object first appeared on the database', - verbose_name='created')), - ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, - help_text='when the object was last modified', - verbose_name='modified')), - ('email', - models.EmailField(help_text='user email address', max_length=254, unique=True, verbose_name='email')), - ('phone_number', - models.CharField(blank=True, help_text='user phone number', max_length=20, null=True, unique=True, - validators=[vibes_auth.validators.validate_phone_number], - verbose_name='phone_number')), - ('first_name', models.CharField(blank=True, max_length=150, null=True, verbose_name='first_name')), - ('last_name', models.CharField(blank=True, max_length=150, null=True, verbose_name='last_name')), - ('avatar', models.ImageField(blank=True, help_text='user profile image', null=True, - upload_to=vibes_auth.models.User.get_uuid_as_path, verbose_name='avatar')), - ('is_verified', - models.BooleanField(default=False, help_text='user verification status', verbose_name='is verified')), - ('is_active', models.BooleanField(default=False, help_text='unselect this instead of deleting accounts', - verbose_name='is_active')), - ('is_subscribed', models.BooleanField(default=False, help_text="user's newsletter subscription status", - verbose_name='is_subscribed')), - ('activation_token', models.UUIDField(default=uuid.uuid4, verbose_name='activation token')), - ('language', models.CharField( - choices=[('en-GB', 'English (British)'), ('ar-AR', 'العربية'), ('cs-CZ', 'Česky'), - ('da-DK', 'Dansk'), ('de-DE', 'Deutsch'), ('en-US', 'English (American)'), - ('es-ES', 'Español'), ('fr-FR', 'Français'), ('hi-IN', 'हिंदी'), ('it-IT', 'Italiano'), - ('ja-JP', '日本語'), ('kk-KZ', 'Қазақ'), ('nl-NL', 'Nederlands'), ('pl-PL', 'Polska'), - ('pt-BR', 'Português'), ('ro-RO', 'Română'), ('ru-RU', 'Русский'), - ('zh-hans', '简体中文')], default='en-GB', max_length=7)), - ('attributes', models.JSONField(blank=True, default=dict, null=True, verbose_name='attributes')), - ('groups', models.ManyToManyField(blank=True, - help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', - related_name='user_set', related_query_name='user', to='auth.group', - verbose_name='groups')), - ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', - related_name='user_set', related_query_name='user', - to='auth.permission', verbose_name='user permissions')), + ("password", models.CharField(max_length=128, verbose_name="password")), + ("last_login", models.DateTimeField(blank=True, null=True, verbose_name="last login")), + ( + "is_superuser", + models.BooleanField( + default=False, + help_text="Designates that this user has all permissions without explicitly assigning them.", + verbose_name="superuser status", + ), + ), + ( + "is_staff", + models.BooleanField( + default=False, + help_text="Designates whether the user can log into this admin site.", + verbose_name="staff status", + ), + ), + ("date_joined", models.DateTimeField(default=django.utils.timezone.now, verbose_name="date joined")), + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, help_text="when the object was last modified", verbose_name="modified" + ), + ), + ( + "email", + models.EmailField( + help_text="user email address", max_length=254, unique=True, verbose_name="email" + ), + ), + ( + "phone_number", + models.CharField( + blank=True, + help_text="user phone number", + max_length=20, + null=True, + unique=True, + validators=[vibes_auth.validators.validate_phone_number], + verbose_name="phone_number", + ), + ), + ("first_name", models.CharField(blank=True, max_length=150, null=True, verbose_name="first_name")), + ("last_name", models.CharField(blank=True, max_length=150, null=True, verbose_name="last_name")), + ( + "avatar", + models.ImageField( + blank=True, + help_text="user profile image", + null=True, + upload_to=vibes_auth.models.User.get_uuid_as_path, + verbose_name="avatar", + ), + ), + ( + "is_verified", + models.BooleanField( + default=False, help_text="user verification status", verbose_name="is verified" + ), + ), + ( + "is_active", + models.BooleanField( + default=False, help_text="unselect this instead of deleting accounts", verbose_name="is_active" + ), + ), + ( + "is_subscribed", + models.BooleanField( + default=False, help_text="user's newsletter subscription status", verbose_name="is_subscribed" + ), + ), + ("activation_token", models.UUIDField(default=uuid.uuid4, verbose_name="activation token")), + ( + "language", + models.CharField( + choices=[ + ("en-GB", "English (British)"), + ("ar-AR", "العربية"), + ("cs-CZ", "Česky"), + ("da-DK", "Dansk"), + ("de-DE", "Deutsch"), + ("en-US", "English (American)"), + ("es-ES", "Español"), + ("fr-FR", "Français"), + ("hi-IN", "हिंदी"), + ("it-IT", "Italiano"), + ("ja-JP", "日本語"), + ("kk-KZ", "Қазақ"), + ("nl-NL", "Nederlands"), + ("pl-PL", "Polska"), + ("pt-BR", "Português"), + ("ro-RO", "Română"), + ("ru-RU", "Русский"), + ("zh-hans", "简体中文"), + ], + default="en-GB", + max_length=7, + ), + ), + ("attributes", models.JSONField(blank=True, default=dict, null=True, verbose_name="attributes")), + ( + "groups", + models.ManyToManyField( + blank=True, + help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", + related_name="user_set", + related_query_name="user", + to="auth.group", + verbose_name="groups", + ), + ), + ( + "user_permissions", + models.ManyToManyField( + blank=True, + help_text="Specific permissions for this user.", + related_name="user_set", + related_query_name="user", + to="auth.permission", + verbose_name="user permissions", + ), + ), ], options={ - 'verbose_name': 'user', - 'verbose_name_plural': 'users', - 'swappable': 'AUTH_USER_MODEL', + "verbose_name": "user", + "verbose_name_plural": "users", + "swappable": "AUTH_USER_MODEL", }, managers=[ - ('objects', vibes_auth.managers.UserManager()), + ("objects", vibes_auth.managers.UserManager()), ], ), ] diff --git a/vibes_auth/migrations/0002_blacklistedtoken_outstandingtoken.py b/vibes_auth/migrations/0002_blacklistedtoken_outstandingtoken.py index 01cc3c8f..e7b4a20a 100644 --- a/vibes_auth/migrations/0002_blacklistedtoken_outstandingtoken.py +++ b/vibes_auth/migrations/0002_blacklistedtoken_outstandingtoken.py @@ -4,37 +4,34 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ - ('token_blacklist', '0012_alter_outstandingtoken_user'), - ('vibes_auth', '0001_initial'), + ("token_blacklist", "0012_alter_outstandingtoken_user"), + ("vibes_auth", "0001_initial"), ] operations = [ migrations.CreateModel( - name='BlacklistedToken', - fields=[ - ], + name="BlacklistedToken", + fields=[], options={ - 'verbose_name': 'blacklisted token', - 'verbose_name_plural': 'blacklisted tokens', - 'proxy': True, - 'indexes': [], - 'constraints': [], + "verbose_name": "blacklisted token", + "verbose_name_plural": "blacklisted tokens", + "proxy": True, + "indexes": [], + "constraints": [], }, - bases=('token_blacklist.blacklistedtoken',), + bases=("token_blacklist.blacklistedtoken",), ), migrations.CreateModel( - name='OutstandingToken', - fields=[ - ], + name="OutstandingToken", + fields=[], options={ - 'verbose_name': 'outstanding token', - 'verbose_name_plural': 'outstanding tokens', - 'proxy': True, - 'indexes': [], - 'constraints': [], + "verbose_name": "outstanding token", + "verbose_name_plural": "outstanding tokens", + "proxy": True, + "indexes": [], + "constraints": [], }, - bases=('token_blacklist.outstandingtoken',), + bases=("token_blacklist.outstandingtoken",), ), ] diff --git a/vibes_auth/migrations/0003_alter_user_language.py b/vibes_auth/migrations/0003_alter_user_language.py index 275a6145..92f7e0ca 100644 --- a/vibes_auth/migrations/0003_alter_user_language.py +++ b/vibes_auth/migrations/0003_alter_user_language.py @@ -5,54 +5,53 @@ from django.db.models.functions import Lower def forwards(apps, schema_editor): if schema_editor: pass - User = apps.get_model('vibes_auth', 'User') - User.objects.all().update(language=Lower('language')) + User = apps.get_model("vibes_auth", "User") + User.objects.all().update(language=Lower("language")) def backwards(apps, schema_editor): if schema_editor: pass - User = apps.get_model('vibes_auth', 'User') + User = apps.get_model("vibes_auth", "User") for u in User.objects.all(): - parts = u.language.split('-', 1) + parts = u.language.split("-", 1) if len(parts) == 2: u.language = f"{parts[0].lower()}-{parts[1].upper()}" - u.save(update_fields=['language']) + u.save(update_fields=["language"]) class Migration(migrations.Migration): dependencies = [ - ('vibes_auth', '0002_blacklistedtoken_outstandingtoken'), + ("vibes_auth", "0002_blacklistedtoken_outstandingtoken"), ] operations = [ migrations.RunPython(forwards, backwards), - migrations.AlterField( - model_name='user', - name='language', + model_name="user", + name="language", field=models.CharField( choices=[ - ('en-gb', 'English (British)'), - ('ar-ar', 'العربية'), - ('cs-cz', 'Česky'), - ('da-dk', 'Dansk'), - ('de-de', 'Deutsch'), - ('en-us', 'English (American)'), - ('es-es', 'Español'), - ('fr-fr', 'Français'), - ('hi-in', 'हिंदी'), - ('it-it', 'Italiano'), - ('ja-jp', '日本語'), - ('kk-kz', 'Қазақ'), - ('nl-nl', 'Nederlands'), - ('pl-pl', 'Polska'), - ('pt-br', 'Português'), - ('ro-ro', 'Română'), - ('ru-ru', 'Русский'), - ('zh-hans', '简体中文'), + ("en-gb", "English (British)"), + ("ar-ar", "العربية"), + ("cs-cz", "Česky"), + ("da-dk", "Dansk"), + ("de-de", "Deutsch"), + ("en-us", "English (American)"), + ("es-es", "Español"), + ("fr-fr", "Français"), + ("hi-in", "हिंदी"), + ("it-it", "Italiano"), + ("ja-jp", "日本語"), + ("kk-kz", "Қазақ"), + ("nl-nl", "Nederlands"), + ("pl-pl", "Polska"), + ("pt-br", "Português"), + ("ro-ro", "Română"), + ("ru-ru", "Русский"), + ("zh-hans", "简体中文"), ], - default='en-gb', + default="en-gb", max_length=7, ), ), diff --git a/vibes_auth/models.py b/vibes_auth/models.py index 797b1091..fe7f0dda 100644 --- a/vibes_auth/models.py +++ b/vibes_auth/models.py @@ -1,4 +1,3 @@ -import uuid from uuid import uuid4 from django.contrib.auth.models import AbstractUser @@ -29,12 +28,62 @@ from vibes_auth.managers import UserManager from vibes_auth.validators import validate_phone_number -class User(AbstractUser, NiceModel): +class User(AbstractUser, NiceModel): # type: ignore [django-manager-missing] + """ + Represents a User entity with customized fields and methods for extended functionality. + + This class extends the AbstractUser model and integrates additional features like + custom email login, validation methods, subscription status, verification, and + attributes storage. It also provides utilities for managing recently viewed items and + token-based activation for verifying accounts. The User model is designed to handle + specific use cases for enhanced user management. + + Attributes: + email: EmailField to store the user's email address. + phone_number: CharField for the user's phone number, allowing for optional storage and validation. + username: Has been set to None as email is the primary unique identifier. + first_name: Optional CharField for the user's first name. + last_name: Optional CharField for the user's last name. + avatar: ImageField for storing the path to the user's profile picture. + is_verified: BooleanField indicating whether the user's email has been verified. + is_active: BooleanField to toggle user activity without deleting the account. + is_subscribed: BooleanField indicating the user's newsletter subscription status. + activation_token: UUIDField for assigning a unique activation token to the user. + language: CharField storing the user's preferred language setting. + attributes: JSONField for custom storage of user-specific additional attributes. + USERNAME_FIELD: Specifies the unique identifier for the user (email in this case). + REQUIRED_FIELDS: A list of fields required when creating a user via createsuperuser, left empty here. + objects: Custom manager for the User model providing additional methods for user creation. + payments_balance: Reference to the user's payment balance (related to the external model). + user_related_wishlist: Reference to the user's wishlist (related to the external model). + orders: QuerySet representing the user's associated orders. + + Methods: + add_to_recently_viewed(product_uuid): + Adds a product's UUID to the user's recently viewed items cache. Keeps a maximum + of 48 items and maintains their order of viewing. + + recently_viewed: (read-only property) + Retrieves a list of UUIDs representing the products recently viewed by the user + from the cache. + + check_token(token): + Validates the input token against the user's activation token. + + __str__(): + Returns the string representation of the user, which is the email address. + + Meta: + swappable: Configures the model to be replaceable with another user model. + verbose_name: Sets the human-readable name for singular instances of the model. + verbose_name_plural: Sets the human-readable name for multiple instances of the model. + """ + def get_uuid_as_path(self, *args): return str(self.uuid) + "/" + args[0] - email: str = EmailField(_("email"), unique=True, help_text=_("user email address")) # type: ignore - phone_number: str = CharField( # type: ignore + email = EmailField(_("email"), unique=True, help_text=_("user email address")) + phone_number = CharField( _("phone_number"), max_length=20, unique=True, @@ -45,9 +94,9 @@ class User(AbstractUser, NiceModel): validate_phone_number, ], ) - username = None - first_name: str = CharField(_("first_name"), max_length=150, blank=True, null=True) # type: ignore - last_name: str = CharField(_("last_name"), max_length=150, blank=True, null=True) # type: ignore + username: None = None # type: ignore [assignment] + first_name = CharField(_("first_name"), max_length=150, blank=True, null=True) # type: ignore [assignment] + last_name = CharField(_("last_name"), max_length=150, blank=True, null=True) # type: ignore [assignment] avatar = ImageField( null=True, verbose_name=_("avatar"), @@ -56,28 +105,28 @@ class User(AbstractUser, NiceModel): help_text=_("user profile image"), ) - is_verified: bool = BooleanField( # type: ignore + is_verified = BooleanField( default=False, verbose_name=_("is verified"), help_text=_("user verification status"), ) - is_active: bool = BooleanField( # type: ignore + is_active = BooleanField( _("is_active"), default=False, help_text=_("unselect this instead of deleting accounts"), ) - is_subscribed: bool = BooleanField( # type: ignore + is_subscribed = BooleanField( verbose_name=_("is_subscribed"), help_text=_("user's newsletter subscription status"), default=False ) - activation_token: uuid = UUIDField(default=uuid4, verbose_name=_("activation token")) # type: ignore - language: str = CharField(choices=LANGUAGES, default=LANGUAGE_CODE, null=False, blank=False, max_length=7) # type: ignore - attributes: dict = JSONField(verbose_name=_("attributes"), default=dict, blank=True, null=True) # type: ignore + activation_token = UUIDField(default=uuid4, verbose_name=_("activation token")) + language = CharField(choices=LANGUAGES, default=LANGUAGE_CODE, null=False, blank=False, max_length=7) + attributes = JSONField(verbose_name=_("attributes"), default=dict, blank=True, null=True) USERNAME_FIELD = "email" REQUIRED_FIELDS = [] # noinspection PyClassVar - objects = UserManager() # type: ignore + objects = UserManager() # type: ignore [misc, assignment] payments_balance: "Balance" user_related_wishlist: "Wishlist" @@ -111,6 +160,20 @@ class User(AbstractUser, NiceModel): class Group(BaseGroup): + """ + Proxy model representing a Group entity. + + This class acts as a proxy for the `BaseGroup` model, providing additional + configuration for display and usage purposes. It does not introduce new fields + or behavior but alters representation and metadata for the Group model. + + Attributes: + Meta.proxy (bool): Indicates this is a proxy model. + Meta.verbose_name (str): Human-readable singular name for the Group model. + Meta.verbose_name_plural (str): Human-readable plural name for the Group + model. + """ + class Meta: proxy = True verbose_name = _("group") @@ -118,6 +181,16 @@ class Group(BaseGroup): class OutstandingToken(BaseOutstandingToken): + """ + Represents a proxy model for outstanding tokens. + + This class is a proxy for the `BaseOutstandingToken` model, used to manage + and customize behaviors or configurations related to outstanding tokens. + It does not add additional fields or logic to the base model but allows for + overloading or extending its default functionality as required. + + """ + class Meta: proxy = True verbose_name = _("outstanding token") @@ -125,6 +198,18 @@ class OutstandingToken(BaseOutstandingToken): class BlacklistedToken(BaseBlacklistedToken): + """ + Represents a blacklisted token model in the system. + + This class acts as a Django model proxy and serves the purpose of managing + blacklisted tokens. It inherits from a base class provided for this purpose, + allowing for the extension of functionality or customization of behavior + without altering the original base class's structure. It also defines the + Meta options for the model, affecting its database and administrative + representation. + + """ + class Meta: proxy = True verbose_name = _("blacklisted token") diff --git a/vibes_auth/serializers.py b/vibes_auth/serializers.py index ad9fada6..6a237584 100644 --- a/vibes_auth/serializers.py +++ b/vibes_auth/serializers.py @@ -16,6 +16,7 @@ from rest_framework.fields import ( EmailField, ListField, SerializerMethodField, + JSONField, ) from rest_framework.serializers import ModelSerializer, Serializer from rest_framework_simplejwt.exceptions import TokenError @@ -30,7 +31,7 @@ from core.utils.security import is_safe_key from evibes import settings from vibes_auth.models import User -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") class UserSerializer(ModelSerializer): @@ -38,6 +39,7 @@ class UserSerializer(ModelSerializer): password = CharField(write_only=True, required=False) is_staff = BooleanField(read_only=True) recently_viewed = SerializerMethodField(required=False, read_only=True) + attributes = JSONField(required=False) @staticmethod def get_avatar_url(obj) -> str: @@ -53,6 +55,7 @@ class UserSerializer(ModelSerializer): "avatar_url", "is_staff", "recently_viewed", + "attributes", "first_name", "last_name", "password", @@ -98,9 +101,7 @@ class UserSerializer(ModelSerializer): """ # noinspection PyTypeChecker return ProductSimpleSerializer( - instance=Product.objects.filter( - uuid__in=obj.recently_viewed, is_active=True - ), + instance=Product.objects.filter(uuid__in=obj.recently_viewed, is_active=True), many=True, ).data @@ -114,7 +115,7 @@ class TokenObtainSerializer(Serializer): def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) - self.user = None + self.user: User | None = None self.fields[self.username_field] = CharField(write_only=True) self.fields["password"] = PasswordField() @@ -126,19 +127,22 @@ class TokenObtainSerializer(Serializer): with suppress(KeyError): authenticate_kwargs["request"] = self.context["request"] - self.user = authenticate(**authenticate_kwargs) # type: ignore + self.user: User | None = authenticate(**authenticate_kwargs) if not api_settings.USER_AUTHENTICATION_RULE(self.user): raise AuthenticationFailed( self.error_messages["no_active_account"], - _("no active account"), # type: ignore + str(_("no active account")), ) return {} @classmethod def get_token(cls, user: AuthUser) -> Token: - return cls.token_class.for_user(user) # type: ignore + if cls.token_class is not None: + return cls.token_class.for_user(user) + else: + raise RuntimeError(_("must set token_class attribute on class.")) class TokenObtainPairSerializer(TokenObtainSerializer): @@ -149,15 +153,22 @@ class TokenObtainPairSerializer(TokenObtainSerializer): logger.debug("Data validated") - refresh = self.get_token(self.user) # type: ignore + if self.user is None: + raise ValidationError(_("no active account")) + + refresh = self.get_token(self.user) data["refresh"] = str(refresh) - data["access"] = str(refresh.access_token) # type: ignore + # noinspection PyUnresolvedReferences + data["access"] = str(refresh.access_token) # type: ignore [attr-defined] data["user"] = UserSerializer(self.user).data logger.debug("Data formed") if api_settings.UPDATE_LAST_LOGIN: - update_last_login(self.user, self.user) # type: ignore + if not self.user: + raise ValidationError(_("no active account")) + # noinspection PyTypeChecker + update_last_login(User, self.user) logger.debug("Updated last login") logger.debug("Returning data") @@ -185,7 +196,8 @@ class TokenRefreshSerializer(Serializer): data["refresh"] = str(refresh) user = User.objects.get(uuid=refresh.payload["user_uuid"]) - data["user"] = UserSerializer(user).data # type: ignore + # noinspection PyTypeChecker + data["user"] = UserSerializer(user).data # type: ignore [assignment] return data @@ -206,18 +218,19 @@ class TokenVerifySerializer(Serializer): try: payload = UntypedToken(attrs["token"]).payload - except TokenError: - raise ValidationError(_("invalid token")) + except TokenError as te: + raise ValidationError(_("invalid token")) from te try: user_uuid = payload["user_uuid"] user = User.objects.get(uuid=user_uuid) - except KeyError: - raise ValidationError(_("no user uuid claim present in token")) - except User.DoesNotExist: - raise ValidationError(_("user does not exist")) + except KeyError as ke: + raise ValidationError(_("no user uuid claim present in token")) from ke + except User.DoesNotExist as dne: + raise ValidationError(_("user does not exist")) from dne - attrs["user"] = UserSerializer(user).data # type: ignore + # noinspection PyTypeChecker + attrs["user"] = UserSerializer(user).data # type: ignore [assignment] return attrs diff --git a/vibes_auth/tasks.py b/vibes_auth/tasks.py index 8f782fbf..aa103eb6 100644 --- a/vibes_auth/tasks.py +++ b/vibes_auth/tasks.py @@ -4,7 +4,7 @@ from core.models import Order, Wishlist from vibes_auth.models import User -@shared_task +@shared_task(queue="default") def create_pending_order(user_uuid): try: user = User.objects.get(uuid=user_uuid) @@ -14,7 +14,7 @@ def create_pending_order(user_uuid): return False, f"Bad uuid was given: {user_uuid}" -@shared_task +@shared_task(queue="default") def create_wishlist(user_uuid): try: user = User.objects.get(uuid=user_uuid) diff --git a/vibes_auth/templates/user_reset_password_email.html b/vibes_auth/templates/user_reset_password_email.html index 3609f0ef..0d1b7946 100644 --- a/vibes_auth/templates/user_reset_password_email.html +++ b/vibes_auth/templates/user_reset_password_email.html @@ -82,7 +82,7 @@
diff --git a/vibes_auth/templates/user_verification_email.html b/vibes_auth/templates/user_verification_email.html index 620f437d..cdf79504 100644 --- a/vibes_auth/templates/user_verification_email.html +++ b/vibes_auth/templates/user_verification_email.html @@ -82,7 +82,7 @@ diff --git a/vibes_auth/urls.py b/vibes_auth/urls.py index ad3bc32c..d09ffedb 100644 --- a/vibes_auth/urls.py +++ b/vibes_auth/urls.py @@ -4,6 +4,8 @@ from rest_framework.routers import DefaultRouter from vibes_auth.views import TokenObtainPairView, TokenRefreshView, TokenVerifyView from vibes_auth.viewsets import UserViewSet +app_name = "vibes_auth" + auth_router = DefaultRouter() auth_router.register(r"users", UserViewSet, basename="users") diff --git a/vibes_auth/utils/emailing.py b/vibes_auth/utils/emailing.py index 25f262ad..de97955f 100644 --- a/vibes_auth/utils/emailing.py +++ b/vibes_auth/utils/emailing.py @@ -13,7 +13,7 @@ from core.utils.constance import set_email_settings from vibes_auth.models import User -@shared_task +@shared_task(queue="default") def send_verification_email_task(user_pk: str) -> tuple[bool, str]: try: user = User.objects.get(pk=user_pk) @@ -52,10 +52,10 @@ def send_verification_email_task(user_pk: str) -> tuple[bool, str]: return False, f"Something went wrong while sending an email: {e!s}" else: - return True, user.uuid + return True, str(user.uuid) -@shared_task +@shared_task(queue="default") def send_reset_password_email_task(user_pk: str) -> tuple[bool, str]: try: user = User.objects.get(pk=user_pk) @@ -95,4 +95,4 @@ def send_reset_password_email_task(user_pk: str) -> tuple[bool, str]: return False, f"Something went wrong while sending an email: {e!s}" else: - return True, user.uuid + return True, str(user.uuid) diff --git a/vibes_auth/views.py b/vibes_auth/views.py index ef12276d..39326f5d 100644 --- a/vibes_auth/views.py +++ b/vibes_auth/views.py @@ -19,13 +19,36 @@ from vibes_auth.serializers import ( TokenVerifySerializer, ) -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") @extend_schema_view(**TOKEN_OBTAIN_SCHEMA) class TokenObtainPairView(TokenViewBase): - serializer_class = TokenObtainPairSerializer # type: ignore - _serializer_class = TokenObtainPairSerializer # type: ignore + """ + Represents a view for getting a pair of access and refresh tokens. + + This view manages the process of handling token-based authentication where + clients can get a pair of JWT tokens (access and refresh) using provided + credentials. It is built on top of a base token view and ensures proper + rate limiting to protect against brute force attacks. + + Attributes: + serializer_class: Serializer class used for processing request data + and returning response data. + _serializer_class: Internal serializer class reference. + + Usage: + This view should be used in authentication-related APIs where clients + need to get new sets of tokens. It incorporates both a serializer for + processing incoming data and also rate limiting to enforce request limits. + + Methods: + post: Handles HTTP POST requests for token retrieval. This method is + subject to rate limiting depending on the global DEBUG setting. + """ + + serializer_class = TokenObtainPairSerializer # type: ignore [assignment] + _serializer_class = TokenObtainPairSerializer # type: ignore [assignment] @method_decorator(ratelimit(key="ip", rate="10/h" if not DEBUG else "888/h")) def post(self, request, *args, **kwargs): @@ -34,8 +57,33 @@ class TokenObtainPairView(TokenViewBase): @extend_schema_view(**TOKEN_REFRESH_SCHEMA) class TokenRefreshView(TokenViewBase): - serializer_class = TokenRefreshSerializer # type: ignore - _serializer_class = TokenRefreshSerializer # type: ignore + """ + Handles refreshing of tokens for authentication purposes. + + This class is used to provide functionality for token refresh + operations as part of an authentication system. It ensures that + clients can request a refreshed token within defined rate limits. + The view relies on the associated serializer to validate token + refresh inputs and produce appropriate outputs. + + Attributes: + serializer_class (Serializer): The serializer used to handle + token refresh operations. This establishes the validation + and processing logic for incoming requests. + + _serializer_class (Serializer): Internal reference to the + serializer, typically used for ensuring consistent processing + for refresh-related logic. + + Methods: + post: Handles HTTP POST requests to refresh the token. + Rate limits requests based on the IP of the client submitting + the request. Rate limit settings are defined depending on + whether the application is in DEBUG mode or not. + """ + + serializer_class = TokenRefreshSerializer # type: ignore [assignment] + _serializer_class = TokenRefreshSerializer # type: ignore [assignment] @method_decorator(ratelimit(key="ip", rate="10/h" if not DEBUG else "888/h")) def post(self, request, *args, **kwargs): @@ -44,8 +92,20 @@ class TokenRefreshView(TokenViewBase): @extend_schema_view(**TOKEN_VERIFY_SCHEMA) class TokenVerifyView(TokenViewBase): - serializer_class = TokenVerifySerializer # type: ignore - _serializer_class = TokenVerifySerializer # type: ignore + """ + Represents a view for verifying JSON Web Tokens (JWT) using specific serialization + and validation logic. + + This class inherits from the `TokenViewBase` and is designed to handle the POST + request for verifying JWT tokens. Tokens are validated using the associated + `TokenVerifySerializer`. The view processes incoming requests, validates tokens, + and returns a response indicating whether the token is valid. If valid, associated + user data can also be returned. Errors during token validation result in an appropriate + error response. + """ + + serializer_class = TokenVerifySerializer # type: ignore [assignment] + _serializer_class = TokenVerifySerializer # type: ignore [assignment] def post(self, request, *args, **kwargs): try: diff --git a/vibes_auth/viewsets.py b/vibes_auth/viewsets.py index eafb2c34..18373a36 100644 --- a/vibes_auth/viewsets.py +++ b/vibes_auth/viewsets.py @@ -27,7 +27,7 @@ from vibes_auth.serializers import ( ) from vibes_auth.utils.emailing import send_reset_password_email_task -logger = logging.getLogger(__name__) +logger = logging.getLogger("django") @extend_schema_view(**USER_SCHEMA) @@ -38,6 +38,47 @@ class UserViewSet( mixins.DestroyModelMixin, GenericViewSet, ): + """ + User view set implementation. + + Provides a set of actions that manage user-related data such as creation, + retrieval, updates, deletion, and custom actions including password reset, + avatar upload, account activation, and recently viewed items merging. + This class extends the mixins and GenericViewSet for robust API handling. + + Attributes: + serializer_class (class): Serializer class used to serialize the user data. + queryset (QuerySet): Queryset that fetches active user objects. + permission_classes (list): List of permissions applied to certain actions. + + Methods: + reset_password(request): + Sends a reset password email to a user based on the provided email. + upload_avatar(request, **_kwargs): + Allows an authenticated user to upload an avatar for their profile. + confirm_password_reset(request, *_args, **_kwargs): + Confirms the password reset and updates the new password for a user. + create(request, *args, **kwargs): + Creates a new user instance using the provided payload. + activate(request): + Activates a user account based on their unique activation link. + merge_recently_viewed(request, **_kwargs): + Merges a list of recently viewed products into the user's profile. + retrieve(request, pk=None, *args, **kwargs): + Retrieves user details for the given user ID. + update(request, pk=None, *args, **kwargs): + Updates user details for the given user ID. + + Raises: + DoesNotExist: + Raised when a user is not found in specific methods working with + database queries. + ValidationError: + Raised for invalid data during serialization or password validation. + OverflowError, TypeError: + Raised for decoding or type conversion issues. + """ + serializer_class = UserSerializer queryset = User.objects.filter(is_active=True) permission_classes = [AllowAny] @@ -74,7 +115,7 @@ class UserViewSet( status=status.HTTP_400_BAD_REQUEST, ) - uuid = urlsafe_base64_decode(request.data.get("uidb64")).decode() + uuid = urlsafe_base64_decode(request.data.get("uidb_64")).decode() user = User.objects.get(pk=uuid) validate_password(password=request.data.get("password"), user=user)