forked from CGM_Public/pretix_original
Compare commits
105
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73bec00d0c | ||
|
|
879ae386ac | ||
|
|
d19cdfb83f | ||
|
|
b404f6d619 | ||
|
|
dda1368d81 | ||
|
|
ddade60625 | ||
|
|
b1e8e072d4 | ||
|
|
b6ade23c50 | ||
|
|
6573578ef1 | ||
|
|
33fc752a5f | ||
|
|
ff043e98f3 | ||
|
|
ddfe065ebd | ||
|
|
bd5b63a90e | ||
|
|
0432798d23 | ||
|
|
ecb2865cb8 | ||
|
|
43a05e1cb3 | ||
|
|
fa28b9c13a | ||
|
|
8a2b38792a | ||
|
|
6652c2e61a | ||
|
|
88b3f588b8 | ||
|
|
eabcececb0 | ||
|
|
31a2a40bce | ||
|
|
a6e897b481 | ||
|
|
a000bacb1f | ||
|
|
b60d38ff3b | ||
|
|
dea47a4e87 | ||
|
|
78e2ea4fef | ||
|
|
9173832ce1 | ||
|
|
d7c9e82bae | ||
|
|
fb7a540efb | ||
|
|
f57a9cbae0 | ||
|
|
fdff1c80d3 | ||
|
|
986122e7f8 | ||
|
|
5dbb01342a | ||
|
|
f81c388906 | ||
|
|
63bc6c17c9 | ||
|
|
5c8d1fde32 | ||
|
|
d0b449ea89 | ||
|
|
377117548d | ||
|
|
634445b79d | ||
|
|
496e4c800a | ||
|
|
83fe53ac2b | ||
|
|
534e6eb32d | ||
|
|
23b863df96 | ||
|
|
fbca5e3ab1 | ||
|
|
37f6b7023c | ||
|
|
d5ed1b87a1 | ||
|
|
2b0f754f4b | ||
|
|
aaebcae12b | ||
|
|
8096e958b8 | ||
|
|
1eb3a09240 | ||
|
|
b52cbf2645 | ||
|
|
40679bc0d8 | ||
|
|
28c04acd81 | ||
|
|
0de588a566 | ||
|
|
a3bf7e37e7 | ||
|
|
c91f2d9f7d | ||
|
|
1511c6c2b4 | ||
|
|
550826af76 | ||
|
|
2b479f59d5 | ||
|
|
861c689410 | ||
|
|
c612f183ef | ||
|
|
2b482dd233 | ||
|
|
3c9874b328 | ||
|
|
342506c866 | ||
|
|
bc84664b1f | ||
|
|
7b8f7f48b9 | ||
|
|
b1c252a646 | ||
|
|
2774eb442d | ||
|
|
27f0ed69d7 | ||
|
|
e1b1bb93bc | ||
|
|
35f160929c | ||
|
|
70507a3a14 | ||
|
|
79c969beab | ||
|
|
46cd5428ff | ||
|
|
0d4a6fc30a | ||
|
|
51abcacf12 | ||
|
|
88a7ef14e1 | ||
|
|
81624c63b5 | ||
|
|
7e070b5a3f | ||
|
|
d78c2f4941 | ||
|
|
c27d9b713f | ||
|
|
e4107360a1 | ||
|
|
d9e53df6ef | ||
|
|
6456a6ae65 | ||
|
|
624fd9e1be | ||
|
|
1d85857c87 | ||
|
|
8ff5f543b2 | ||
|
|
ad06aa3e67 | ||
|
|
dc7cbe8c46 | ||
|
|
dd7f0ca0e4 | ||
|
|
93d799d9b9 | ||
|
|
e725b384e3 | ||
|
|
63852ad344 | ||
|
|
170399a883 | ||
|
|
0dd274287c | ||
|
|
eebe9c7237 | ||
|
|
d4b210c164 | ||
|
|
8a6488fd81 | ||
|
|
c52ebb4ba9 | ||
|
|
0121e053f6 | ||
|
|
464a25a678 | ||
|
|
3eceb33cfc | ||
|
|
e9b22b7d33 | ||
|
|
5ad0f92776 |
+11
-11
@@ -25,7 +25,7 @@ and what you should think of.
|
||||
Scaling reasons
|
||||
---------------
|
||||
|
||||
There's mainly two reasons to scale up a pretix installation beyond a single server:
|
||||
There are two main reasons for scaling up a pretix installation beyond a single server:
|
||||
|
||||
* **Availability:** Distributing pretix over multiple servers can allow you to survive failure of one or more single machines, leading to a higher uptime and reliability of your system.
|
||||
|
||||
@@ -92,7 +92,7 @@ them from a different URL <config-urls>`.
|
||||
pretix-web
|
||||
""""""""""
|
||||
|
||||
The ``pretix-web`` process does not carry any internal state can be easily started on as many machines as you like, and you can
|
||||
The ``pretix-web`` process does not carry any internal state and can be easily started on as many machines as you like, and you can
|
||||
use the load balancing features of your frontend web server to redirect to all of them.
|
||||
|
||||
You can adjust the number of processes in the ``gunicorn`` command line, and we recommend choosing roughly two times the number
|
||||
@@ -154,7 +154,7 @@ files, otherwise you **will** run into errors with the user interface.
|
||||
The easiest solution for this is probably to store them on a NFS server that you mount
|
||||
on each of the other servers.
|
||||
|
||||
Since we use Django's file storage mechanism internally, you can in theory also use a object-storage solution like Amazon S3, Ceph, or Minio to store these files, although we currently do not expose this through pretix' configuration file and this would require you to ship your own variant of ``pretix/settings.py`` and reference it through the ``DJANGO_SETTINGS_MODULE`` environment variable.
|
||||
Since we use Django's file storage mechanism internally, you can in theory also use an object-storage solution like Amazon S3, Ceph, or Minio to store these files, although we currently do not expose this through pretix' configuration file and this would require you to ship your own variant of ``pretix/settings.py`` and reference it through the ``DJANGO_SETTINGS_MODULE`` environment variable.
|
||||
|
||||
At pretix.eu, we use a custom-built `object storage cluster`_.
|
||||
|
||||
@@ -171,12 +171,12 @@ you configure, so make sure to set this memory usage as high as you can afford.
|
||||
memory available allows your database to make more use of caching, which is usually good.
|
||||
|
||||
Scaling your database to multiple machines needs to be treated with great caution. It's a
|
||||
good to have a replica of your database for availability reasons. In case your primary
|
||||
good idea to have a replica of your database for availability reasons. In case your primary
|
||||
database server fails, you can easily switch over to the replica and continue working.
|
||||
|
||||
However, using database replicas for performance gains is much more complicated. When using
|
||||
However, using database replicas for performance gain is much more complicated. When using
|
||||
replicated database systems, you are always trading in consistency or availability to get
|
||||
additional performance and the consequences of this can be subtle and it is important
|
||||
additional performance and the consequences of this can be subtle. It is important
|
||||
that you have a deep understanding of the semantics of your replication mechanism.
|
||||
|
||||
.. warning::
|
||||
@@ -187,7 +187,7 @@ that you have a deep understanding of the semantics of your replication mechanis
|
||||
As an example, if you buy a ticket, pretix first needs to calculate how many tickets
|
||||
are left to sell. If this calculation is done on a database replica that lags behind
|
||||
even for fractions of a second, the decision to allow selling the ticket will be made
|
||||
on out-of-data data and you can end up with more tickets sold than configured. Similarly,
|
||||
on stale data and you can end up with more tickets sold than configured. Similarly,
|
||||
you could imagine situations leading to double payments etc.
|
||||
|
||||
If you do have a replica, you *can* tell pretix about it :ref:`in your configuration <config-replica>`.
|
||||
@@ -204,9 +204,9 @@ redis
|
||||
While redis is a very important part that glues together some of the components, it isn't used
|
||||
heavily and can usually handle a fairly large pretix installation easily on a single modern
|
||||
CPU core.
|
||||
Having some memory available is good in case of e.g. lots of tasks queuing up during a traffic peak, but we wouldn't expect ever needing more than a gigabyte of it.
|
||||
Having some memory available is good, e.g. if lots of tasks queue up during a traffic peak, but we wouldn't expect ever needing more than a gigabyte of it.
|
||||
|
||||
Feel free to set up a redis cluster for availability – but you won't need it for performance in a long time.
|
||||
Feel free to set up a redis cluster for availability – but you probably won't need it for performance.
|
||||
|
||||
The limitations
|
||||
---------------
|
||||
@@ -228,9 +228,9 @@ if you add more hardware.
|
||||
If you have an unlimited number of tickets, we can apply fewer locking and we've reached **approx.
|
||||
1500 orders per minute per event** in benchmarks, although even more should be possible.
|
||||
|
||||
We're working to reduce the number of cases in which this is relevant and thereby improve the possible
|
||||
We're working on reducing the number of cases in which this is relevant and thereby improve the possible
|
||||
throughput. If you want to use pretix for an event with 10,000+ tickets that are likely to be sold out
|
||||
within minutes, please get in touch to discuss possible solutions. We'll work something out for you!
|
||||
|
||||
|
||||
.. _object storage cluster: https://behind.pretix.eu/2018/03/20/high-available-cdn/
|
||||
.. _object storage cluster: https://behind.pretix.eu/2018/03/20/high-available-cdn/
|
||||
|
||||
@@ -225,4 +225,3 @@ You can get three response codes:
|
||||
"subevent": 23,
|
||||
"checkinlist": 5
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,10 @@ failed scans.
|
||||
|
||||
The endpoints listed on this page have been added.
|
||||
|
||||
.. versionchanged:: 4.18
|
||||
|
||||
The ``source_type`` parameter has been added.
|
||||
|
||||
.. _`rest-checkin-redeem`:
|
||||
|
||||
Checking a ticket in
|
||||
@@ -28,6 +32,7 @@ Checking a ticket in
|
||||
passed needs to be from a distinct event.
|
||||
|
||||
:<json string secret: Scanned QR code corresponding to the ``secret`` attribute of a ticket.
|
||||
:<json string source_type: Type of source the ``secret`` was obtained form. Defaults to ``"barcode"``.
|
||||
:<json array lists: List of check-in list IDs to search on. No two check-in lists may be from the same event.
|
||||
:<json string type: Send ``"exit"`` for an exit and ``"entry"`` (default) for an entry.
|
||||
:<json datetime datetime: Specifies the datetime of the check-in. If not supplied, the current time will be used.
|
||||
@@ -72,6 +77,7 @@ Checking a ticket in
|
||||
|
||||
{
|
||||
"secret": "M5BO19XmFwAjLd4nDYUAL9ISjhti0e9q",
|
||||
"source_type": "barcode",
|
||||
"lists": [1],
|
||||
"force": false,
|
||||
"ignore_unpaid": false,
|
||||
@@ -213,8 +219,8 @@ Checking a ticket in
|
||||
* ``revoked`` - Ticket code has been revoked.
|
||||
* ``error`` - Internal error.
|
||||
|
||||
In case of reason ``rules``, there might be an additional response field ``reason_explanation`` with a human-readable
|
||||
description of the violated rules. However, that field can also be missing or be ``null``.
|
||||
In case of reason ``rules`` and ``invalid_time``, there might be an additional response field ``reason_explanation``
|
||||
with a human-readable description of the violated rules. However, that field can also be missing or be ``null``.
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:statuscode 201: no error
|
||||
|
||||
@@ -753,8 +753,8 @@ Order position endpoints
|
||||
* ``ambiguous`` - Multiple tickets match scan, rejected.
|
||||
* ``revoked`` - Ticket code has been revoked.
|
||||
|
||||
In case of reason ``rules``, there might be an additional response field ``reason_explanation`` with a human-readable
|
||||
description of the violated rules. However, that field can also be missing or be ``null``.
|
||||
In case of reason ``rules`` or ``invalid_time``, there might be an additional response field ``reason_explanation``
|
||||
with a human-readable description of the violated rules. However, that field can also be missing or be ``null``.
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
|
||||
@@ -547,6 +547,9 @@ Therefore, we're also not including a list of the options here, but instead reco
|
||||
to see available options. The ``explain=true`` flag enables a verbose mode that provides you with human-readable
|
||||
information about the properties.
|
||||
|
||||
Note that some settings are read-only, e.g. because they can be read on event level but currently only be changed on
|
||||
organizer level.
|
||||
|
||||
.. note:: Please note that this is not a complete representation of all event settings. You will find more settings
|
||||
in the web interface.
|
||||
|
||||
@@ -593,6 +596,7 @@ information about the properties.
|
||||
{
|
||||
"value": "https://pretix.eu",
|
||||
"label": "Imprint URL",
|
||||
"readonly": false,
|
||||
"help_text": "This should point e.g. to a part of your website that has your contact details and legal information."
|
||||
}
|
||||
},
|
||||
@@ -606,6 +610,10 @@ information about the properties.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. versionchanged:: 4.18
|
||||
|
||||
The ``readonly`` flag has been added.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/settings/
|
||||
|
||||
Updates event settings. Note that ``PUT`` is not allowed here, only ``PATCH``.
|
||||
|
||||
@@ -32,6 +32,7 @@ at :ref:`plugin-docs`.
|
||||
membershiptypes
|
||||
memberships
|
||||
giftcards
|
||||
reusablemedia
|
||||
carts
|
||||
teams
|
||||
devices
|
||||
|
||||
@@ -108,6 +108,9 @@ generate_tickets boolean If ``false``,
|
||||
allow_waitinglist boolean If ``false``, no waiting list will be shown for this
|
||||
product when it is sold out.
|
||||
issue_giftcard boolean If ``true``, buying this product will yield a gift card.
|
||||
media_policy string Policy on how to handle reusable media (experimental feature).
|
||||
Possible values are ``null``, ``"new"``, ``"reuse"``, and ``"reuse_or_new"``.
|
||||
media_type string Type of reusable media to work on (experimental feature). See :ref:`rest-reusablemedia` for possible choices.
|
||||
show_quota_left boolean Publicly show how many tickets are still available.
|
||||
If this is ``null``, the event default is used.
|
||||
has_variations boolean Shows whether or not this item has variations.
|
||||
@@ -189,6 +192,10 @@ meta_data object Values set fo
|
||||
|
||||
The ``validity_*`` attributes have been added.
|
||||
|
||||
.. versionchanged:: 4.18
|
||||
|
||||
The ``media_policy`` and ``media_type`` attributes have been added.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
@@ -244,6 +251,8 @@ Endpoints
|
||||
"admission": false,
|
||||
"personalized": false,
|
||||
"issue_giftcard": false,
|
||||
"media_policy": null,
|
||||
"media_type": null,
|
||||
"meta_data": {},
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
@@ -373,6 +382,8 @@ Endpoints
|
||||
"admission": false,
|
||||
"personalized": false,
|
||||
"issue_giftcard": false,
|
||||
"media_policy": null,
|
||||
"media_type": null,
|
||||
"meta_data": {},
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
@@ -483,6 +494,8 @@ Endpoints
|
||||
"admission": false,
|
||||
"personalized": false,
|
||||
"issue_giftcard": false,
|
||||
"media_policy": null,
|
||||
"media_type": null,
|
||||
"meta_data": {},
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
@@ -580,6 +593,8 @@ Endpoints
|
||||
"admission": false,
|
||||
"personalized": false,
|
||||
"issue_giftcard": false,
|
||||
"media_policy": null,
|
||||
"media_type": null,
|
||||
"meta_data": {},
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
@@ -709,6 +724,8 @@ Endpoints
|
||||
"admission": false,
|
||||
"personalized": false,
|
||||
"issue_giftcard": false,
|
||||
"media_policy": null,
|
||||
"media_type": null,
|
||||
"meta_data": {},
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
|
||||
@@ -910,6 +910,7 @@ Creating orders
|
||||
* ``valid_from`` (optional, if both ``valid_from`` and ``valid_until`` are **missing** (not ``null``) the availability will be computed from the given product)
|
||||
* ``valid_until`` (optional, if both ``valid_from`` and ``valid_until`` are **missing** (not ``null``) the availability will be computed from the given product)
|
||||
* ``requested_valid_from`` (optional, can be set **instead** of ``valid_from`` and ``valid_until`` to signal a user choice for the start time that may or may not be respected)
|
||||
* ``use_reusable_medium`` (optional, causes the new ticket to take over the given reusable medium, identified by its ID)
|
||||
* ``answers``
|
||||
|
||||
* ``question``
|
||||
|
||||
@@ -157,6 +157,7 @@ information about the properties.
|
||||
{
|
||||
"value": "calendar",
|
||||
"label": "Default overview style",
|
||||
"readonly": false,
|
||||
"help_text": "If your event series has more than 50 dates in the future, only the month or week calendar can be used."
|
||||
}
|
||||
},
|
||||
|
||||
@@ -63,6 +63,7 @@ valid_date_max date Maximum value f
|
||||
valid_datetime_min datetime Minimum value for date and time questions (optional)
|
||||
valid_datetime_max datetime Maximum value for date and time questions (optional)
|
||||
valid_file_portrait boolean Turn on file validation for portrait photos
|
||||
valid_string_length_max integer Maximum length for string questions (optional)
|
||||
dependency_question integer Internal ID of a different question. The current
|
||||
question will only be shown if the question given in
|
||||
this attribute is set to the value given in
|
||||
@@ -122,6 +123,7 @@ Endpoints
|
||||
"valid_date_max": null,
|
||||
"valid_datetime_min": null,
|
||||
"valid_datetime_max": null,
|
||||
"valid_string_length_max": null,
|
||||
"valid_file_portrait": false,
|
||||
"dependency_question": null,
|
||||
"dependency_value": null,
|
||||
@@ -201,6 +203,7 @@ Endpoints
|
||||
"valid_datetime_min": null,
|
||||
"valid_datetime_max": null,
|
||||
"valid_file_portrait": false,
|
||||
"valid_string_length_max": null,
|
||||
"dependency_question": null,
|
||||
"dependency_value": null,
|
||||
"dependency_values": [],
|
||||
@@ -302,6 +305,7 @@ Endpoints
|
||||
"valid_datetime_min": null,
|
||||
"valid_datetime_max": null,
|
||||
"valid_file_portrait": false,
|
||||
"valid_string_length_max": null,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
@@ -384,6 +388,7 @@ Endpoints
|
||||
"valid_datetime_min": null,
|
||||
"valid_datetime_max": null,
|
||||
"valid_file_portrait": false,
|
||||
"valid_string_length_max": null,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
.. _`rest-reusablemedia`:
|
||||
|
||||
Reusable media
|
||||
==============
|
||||
|
||||
Reusable media represent things, typically physical tokens like plastic cards or NFC wristbands, which can represent
|
||||
other entities inside the system. For example, a medium can link to an order position or to a gift card and can be used
|
||||
in their place. Later, the medium might be reused for a different ticket.
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
The reusable medium resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the medium
|
||||
type string Type of medium, e.g. ``"barcode"`` or ``"nfc_uid"``.
|
||||
identifier string Unique identifier of the medium. The format depends on the ``type``.
|
||||
active boolean Whether this medium may be used.
|
||||
created datetime Date of creation
|
||||
updated datetime Date of last modification
|
||||
expires datetime Expiry date (or ``null``)
|
||||
customer string Identifier of a customer account this medium belongs to.
|
||||
linked_orderposition integer Internal ID of a ticket this medium is linked to.
|
||||
linked_giftcard integer Internal ID of a gift card this medium is linked to.
|
||||
info object Additional data, content depends on the ``type``. Consider
|
||||
this internal to the system and don't use it for your own data.
|
||||
notes string Internal notes and comments (or ``null``)
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
Existing media types are:
|
||||
|
||||
- ``barcode``
|
||||
- ``nfc_uid``
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/reusablemedia/
|
||||
|
||||
Returns a list of all media issued by a given organizer.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/reusablemedia/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "ABCDEFGH",
|
||||
"created": "2021-04-06T13:44:22.809377Z",
|
||||
"updated": "2021-04-06T13:44:22.809377Z",
|
||||
"type": "barcode",
|
||||
"active": True,
|
||||
"expires": None,
|
||||
"customer": None,
|
||||
"linked_orderposition": None,
|
||||
"linked_giftcard": None,
|
||||
"notes": None,
|
||||
"info": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1.
|
||||
:query string identifier: Only show media with the given identifier. Note that you should use the lookup endpoint described below for most use cases.
|
||||
:query string type: Only show media with the given type.
|
||||
:query boolean active: Only show media that are (not) active.
|
||||
:query string customer: Only show media linked to the given customer.
|
||||
:query string created_since: Only show media created since a given date.
|
||||
:query string updated_since: Only show media updated since a given date.
|
||||
:query integer linked_orderposition: Only show media linked to the given ticket.
|
||||
:query integer linked_giftcard: Only show media linked to the given gift card.
|
||||
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_orderposition"``, oder ``"customer"``, the respective
|
||||
field will be shown as a nested value instead of just an ID. The nested objects are identical to
|
||||
the respective resources, except that the ``linked_orderposition`` will have an attribute of the
|
||||
format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make matching easier. The parameter
|
||||
can be given multiple times.
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/reusablemedia/(id)/
|
||||
|
||||
Returns information on one medium, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/reusablemedia/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "ABCDEFGH",
|
||||
"created": "2021-04-06T13:44:22.809377Z",
|
||||
"updated": "2021-04-06T13:44:22.809377Z",
|
||||
"type": "barcode",
|
||||
"active": True,
|
||||
"expires": None,
|
||||
"customer": None,
|
||||
"linked_orderposition": None,
|
||||
"linked_giftcard": None,
|
||||
"notes": None,
|
||||
"info": {}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param id: The ``id`` field of the medium to fetch
|
||||
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_orderposition"``, oder ``"customer"``, the respective
|
||||
field will be shown as a nested value instead of just an ID. The nested objects are identical to
|
||||
the respective resources, except that the ``linked_orderposition`` will have an attribute of the
|
||||
format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make matching easier. The parameter
|
||||
can be given multiple times.
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/reusablemedia/lookup/
|
||||
|
||||
Look up a new reusable medium by its identifier. In some cases, this might lead to the automatic creation of a new
|
||||
medium behind the scenes.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/reusablemedia/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"identifier": "ABCDEFGH",
|
||||
"type": "barcode",
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "ABCDEFGH",
|
||||
"created": "2021-04-06T13:44:22.809377Z",
|
||||
"updated": "2021-04-06T13:44:22.809377Z",
|
||||
"type": "barcode",
|
||||
"active": True,
|
||||
"expires": None,
|
||||
"customer": None,
|
||||
"linked_orderposition": None,
|
||||
"linked_giftcard": None,
|
||||
"notes": None,
|
||||
"info": {}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to look up a medium for
|
||||
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_orderposition"``, oder ``"customer"``, the respective
|
||||
field will be shown as a nested value instead of just an ID. The nested objects are identical to
|
||||
the respective resources, except that the ``linked_orderposition`` will have an attribute of the
|
||||
format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make matching easier. The parameter
|
||||
can be given multiple times.
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The medium could not be looked up due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/reusablemedia/
|
||||
|
||||
Creates a new reusable medium.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/reusablemedia/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"identifier": "ABCDEFGH",
|
||||
"type": "barcode",
|
||||
"active": True,
|
||||
"expires": None,
|
||||
"customer": None,
|
||||
"linked_orderposition": None,
|
||||
"linked_giftcard": None,
|
||||
"notes": None,
|
||||
"info": {}
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "ABCDEFGH",
|
||||
"created": "2021-04-06T13:44:22.809377Z",
|
||||
"updated": "2021-04-06T13:44:22.809377Z",
|
||||
"type": "barcode",
|
||||
"active": True,
|
||||
"expires": None,
|
||||
"customer": None,
|
||||
"linked_orderposition": None,
|
||||
"linked_giftcard": None,
|
||||
"notes": None,
|
||||
"info": {}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to create a medium for
|
||||
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_orderposition"``, oder ``"customer"``, the respective
|
||||
field will be shown as a nested value instead of just an ID. The nested objects are identical to
|
||||
the respective resources, except that the ``linked_orderposition`` will have an attribute of the
|
||||
format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make matching easier. The parameter
|
||||
can be given multiple times.
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The medium could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/reusablemedia/(id)/
|
||||
|
||||
Update a reusable medium. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
You can change all fields of the resource except the ``id``, ``identifier`` and ``type`` fields.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/reusablemedia/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"linked_orderposition": 13
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "ABCDEFGH",
|
||||
"created": "2021-04-06T13:44:22.809377Z",
|
||||
"updated": "2021-04-06T13:44:22.809377Z",
|
||||
"type": "barcode",
|
||||
"active": True,
|
||||
"expires": None,
|
||||
"customer": None,
|
||||
"linked_orderposition": 13,
|
||||
"linked_giftcard": None,
|
||||
"notes": None,
|
||||
"info": {}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param id: The ``id`` field of the medium to modify
|
||||
:query string expand: If you pass ``"linked_giftcard"``, ``"linked_orderposition"``, oder ``"customer"``, the respective
|
||||
field will be shown as a nested value instead of just an ID. The nested objects are identical to
|
||||
the respective resources, except that the ``linked_orderposition`` will have an attribute of the
|
||||
format ``"order": {"code": "ABCDE", "event": "eventslug"}`` to make matching easier. The parameter
|
||||
can be given multiple times.
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The medium could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to change this resource.
|
||||
@@ -26,6 +26,7 @@ can_create_events boolean
|
||||
can_change_teams boolean
|
||||
can_change_organizer_settings boolean
|
||||
can_manage_customers boolean
|
||||
can_manage_reusable_media boolean
|
||||
can_manage_gift_cards boolean
|
||||
can_change_event_settings boolean
|
||||
can_change_items boolean
|
||||
@@ -36,6 +37,10 @@ can_change_vouchers boolean
|
||||
can_checkin_orders boolean
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 4.18
|
||||
|
||||
The ``can_manage_reusable_media`` permission has been added.
|
||||
|
||||
Team member resource
|
||||
--------------------
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ The following values for ``action_types`` are valid with pretix core:
|
||||
* ``pretix.event.order.refund.done``
|
||||
* ``pretix.event.order.refund.canceled``
|
||||
* ``pretix.event.order.refund.failed``
|
||||
* ``pretix.event.order.payment.confirmed``
|
||||
* ``pretix.event.order.approved``
|
||||
* ``pretix.event.order.denied``
|
||||
* ``pretix.event.checkin``
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 177 KiB After Width: | Height: | Size: 180 KiB |
@@ -38,27 +38,27 @@ else
|
||||
endif
|
||||
|
||||
"Is the order in status PAID or PENDING\nand is the position not canceled?" --> if "" then
|
||||
-right->[no] "Return error CANCELED"
|
||||
-right->[no && !force] "Return error CANCELED"
|
||||
else
|
||||
-down->[yes] "Is one or more block set on the ticket?"
|
||||
-down->[yes || force] "Is one or more block set on the ticket?"
|
||||
--> if "" then
|
||||
-right->[no] "Return error BLOCKED"
|
||||
-right->[no && !force] "Return error BLOCKED"
|
||||
else
|
||||
-down->[yes] "If this is not an exit, is the valid_from/valid_until\nconstraint on the ticket fulfilled?"
|
||||
-down->[yes || force] "If this is not an exit, is the valid_from/valid_until\nconstraint on the ticket fulfilled?"
|
||||
--> if "" then
|
||||
-right->[no] "Return error INVALID_TIME"
|
||||
-right->[no && !force] "Return error INVALID_TIME"
|
||||
else
|
||||
-down->[yes] "Is the product part of the check-in list?"
|
||||
-down->[yes || force] "Is the product part of the check-in list?"
|
||||
--> if "" then
|
||||
-right->[no] "Return error PRODUCT"
|
||||
-right->[no && !force] "Return error PRODUCT"
|
||||
else
|
||||
-down->[yes] "Is the subevent part of the check-in list?"
|
||||
-down->[yes || force] "Is the subevent part of the check-in list?"
|
||||
--> if "" then
|
||||
-right->[no] "Return error PRODUCT "
|
||||
-right->[no && !force] "Return error PRODUCT "
|
||||
else
|
||||
-down->[yes] "Is the order in status PAID\nor is this a forced upload?"
|
||||
-down->[yes] "Is the order in status PAID?"
|
||||
--> if "" then
|
||||
-right->[no] "Is Order.require_approval set?"
|
||||
-right->[no && !force] "Is Order.require_approval set?"
|
||||
--> if "" then
|
||||
-->[no] "Is Order.valid_if_pending set?"
|
||||
--> if "" then
|
||||
@@ -80,7 +80,7 @@ else
|
||||
-->[yes] "Return error UNPAID "
|
||||
endif
|
||||
else
|
||||
-down->[yes] "Is this an entry or exit?\nIs the upload forced?"
|
||||
-down->[yes || force] "Is this an entry or exit?\nIs the upload forced?"
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -318,7 +318,10 @@ Currently, the following attributes are understood by pretix itself:
|
||||
|
||||
* If ``data-consent="…"`` is given, the cookie consent mechanism will be initialized with consent for the given cookie
|
||||
providers. All other providers will be disabled, no consent dialog will be shown. This is useful if you already
|
||||
asked the user for consent and don't want them to be asked again. Example: ``data-consent="facebook,google_analytics"``
|
||||
asked the user for consent and don't want them to be asked again. Example: ``data-consent="facebook,google_analytics"``
|
||||
|
||||
When using the pretix-tracking plugin, the following values are supported::
|
||||
``adform, facebook, gosquared, google_ads, google_analytics, hubspot, linkedin, matomo, twitter``
|
||||
|
||||
Any configured pretix plugins might understand more data fields. For example, if the appropriate plugins on pretix
|
||||
Hosted or pretix Enterprise are active, you can pass the following fields:
|
||||
|
||||
@@ -19,4 +19,4 @@
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
__version__ = "4.18.0.dev0"
|
||||
__version__ = "4.19.0.dev0"
|
||||
|
||||
@@ -81,6 +81,7 @@ class PretixScanSecurityProfile(AllowListSecurityProfile):
|
||||
('POST', 'api-v1:upload'),
|
||||
('POST', 'api-v1:checkinrpc.redeem'),
|
||||
('GET', 'api-v1:checkinrpc.search'),
|
||||
('GET', 'api-v1:reusablemedium-list'),
|
||||
)
|
||||
|
||||
|
||||
@@ -220,6 +221,7 @@ class PretixPosSecurityProfile(AllowListSecurityProfile):
|
||||
('POST', 'api-v1:upload'),
|
||||
('POST', 'api-v1:checkinrpc.redeem'),
|
||||
('GET', 'api-v1:checkinrpc.search'),
|
||||
('POST', 'api-v1:reusablemedium-lookup'),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ from rest_framework.exceptions import ValidationError
|
||||
from pretix.api.serializers.event import SubEventSerializer
|
||||
from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
||||
from pretix.base.channels import get_all_sales_channels
|
||||
from pretix.base.media import MEDIA_TYPES
|
||||
from pretix.base.models import Checkin, CheckinList
|
||||
|
||||
|
||||
@@ -84,6 +85,7 @@ class CheckinRPCRedeemInputSerializer(serializers.Serializer):
|
||||
lists = serializers.PrimaryKeyRelatedField(required=True, many=True, queryset=CheckinList.objects.none())
|
||||
secret = serializers.CharField(required=True, allow_null=False)
|
||||
force = serializers.BooleanField(default=False, required=False)
|
||||
source_type = serializers.ChoiceField(choices=[(k, v) for k, v in MEDIA_TYPES.items()], default='barcode')
|
||||
type = serializers.ChoiceField(choices=Checkin.CHECKIN_TYPES, default=Checkin.TYPE_ENTRY)
|
||||
ignore_unpaid = serializers.BooleanField(default=False, required=False)
|
||||
questions_supported = serializers.BooleanField(default=True, required=False)
|
||||
|
||||
@@ -797,6 +797,21 @@ class EventSettingsSerializer(SettingsSerializer):
|
||||
'logo_show_title',
|
||||
'og_image',
|
||||
'name_scheme',
|
||||
'reusable_media_active',
|
||||
'reusable_media_type_barcode',
|
||||
'reusable_media_type_barcode_identifier_length',
|
||||
'reusable_media_type_nfc_uid',
|
||||
'reusable_media_type_nfc_uid_autocreate_giftcard',
|
||||
'reusable_media_type_nfc_uid_autocreate_giftcard_currency',
|
||||
]
|
||||
readonly_fields = [
|
||||
# These are read-only since they are currently only settable on organizers, not events
|
||||
'reusable_media_active',
|
||||
'reusable_media_type_barcode',
|
||||
'reusable_media_type_barcode_identifier_length',
|
||||
'reusable_media_type_nfc_uid',
|
||||
'reusable_media_type_nfc_uid_autocreate_giftcard',
|
||||
'reusable_media_type_nfc_uid_autocreate_giftcard_currency',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -863,6 +878,9 @@ class DeviceEventSettingsSerializer(EventSettingsSerializer):
|
||||
'invoice_address_from_tax_id',
|
||||
'invoice_address_from_vat_id',
|
||||
'name_scheme',
|
||||
'reusable_media_type_barcode',
|
||||
'reusable_media_type_nfc_uid',
|
||||
'system_question_order',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
@@ -244,7 +244,8 @@ class ItemSerializer(I18nAwareModelSerializer):
|
||||
'grant_membership_duration_like_event', 'grant_membership_duration_days',
|
||||
'grant_membership_duration_months', 'validity_mode', 'validity_fixed_from', 'validity_fixed_until',
|
||||
'validity_dynamic_duration_minutes', 'validity_dynamic_duration_hours', 'validity_dynamic_duration_days',
|
||||
'validity_dynamic_duration_months', 'validity_dynamic_start_choice', 'validity_dynamic_start_choice_day_limit')
|
||||
'validity_dynamic_duration_months', 'validity_dynamic_start_choice', 'validity_dynamic_start_choice_day_limit',
|
||||
'media_policy', 'media_type')
|
||||
read_only_fields = ('has_variations',)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -263,6 +264,7 @@ class ItemSerializer(I18nAwareModelSerializer):
|
||||
|
||||
Item.clean_per_order(data.get('min_per_order'), data.get('max_per_order'))
|
||||
Item.clean_available(data.get('available_from'), data.get('available_until'))
|
||||
Item.clean_media_settings(self.context['event'], data.get('media_policy'), data.get('media_type'), data.get('issue_giftcard'))
|
||||
|
||||
if data.get('personalized') and not data.get('admission'):
|
||||
raise ValidationError(_('Only admission products can currently be personalized.'))
|
||||
@@ -440,7 +442,7 @@ class QuestionSerializer(I18nAwareModelSerializer):
|
||||
'ask_during_checkin', 'identifier', 'dependency_question', 'dependency_values',
|
||||
'hidden', 'dependency_value', 'print_on_invoice', 'help_text', 'valid_number_min',
|
||||
'valid_number_max', 'valid_date_min', 'valid_date_max', 'valid_datetime_min', 'valid_datetime_max',
|
||||
'valid_file_portrait')
|
||||
'valid_string_length_max', 'valid_file_portrait')
|
||||
|
||||
def validate_identifier(self, value):
|
||||
Question._clean_identifier(self.context['event'], value, self.instance)
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
#
|
||||
# This file is part of pretix (Community Edition).
|
||||
#
|
||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||
#
|
||||
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
|
||||
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
|
||||
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
|
||||
# this file, see <https://pretix.eu/about/en/license>.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
import logging
|
||||
from decimal import Decimal
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
||||
from pretix.api.serializers.order import OrderPositionSerializer
|
||||
from pretix.api.serializers.organizer import (
|
||||
CustomerSerializer, GiftCardSerializer,
|
||||
)
|
||||
from pretix.base.models import Order, OrderPosition, ReusableMedium
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NestedOrderMiniSerializer(I18nAwareModelSerializer):
|
||||
event = serializers.SlugRelatedField(slug_field='slug', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Order
|
||||
fields = ['code', 'event']
|
||||
|
||||
|
||||
class NestedOrderPositionSerializer(OrderPositionSerializer):
|
||||
order = NestedOrderMiniSerializer()
|
||||
|
||||
|
||||
class NestedGiftCardSerializer(GiftCardSerializer):
|
||||
|
||||
def to_representation(self, instance):
|
||||
d = super().to_representation(instance)
|
||||
if hasattr(instance, 'cached_value'):
|
||||
d['value'] = str(Decimal(instance.cached_value).quantize(Decimal("0.01")))
|
||||
else:
|
||||
d['value'] = str(Decimal(instance.value).quantize(Decimal("0.01")))
|
||||
return d
|
||||
|
||||
|
||||
class ReusableMediaSerializer(I18nAwareModelSerializer):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if 'linked_giftcard' in self.context['request'].query_params.getlist('expand'):
|
||||
self.fields['linked_giftcard'] = NestedGiftCardSerializer(read_only=True)
|
||||
else:
|
||||
self.fields['linked_giftcard'] = serializers.PrimaryKeyRelatedField(
|
||||
required=False,
|
||||
allow_null=True,
|
||||
queryset=self.context['organizer'].issued_gift_cards.all()
|
||||
)
|
||||
|
||||
if 'linked_orderposition' in self.context['request'].query_params.getlist('expand'):
|
||||
self.fields['linked_orderposition'] = NestedOrderPositionSerializer(read_only=True)
|
||||
else:
|
||||
self.fields['linked_orderposition'] = serializers.PrimaryKeyRelatedField(
|
||||
required=False,
|
||||
allow_null=True,
|
||||
queryset=OrderPosition.all.filter(order__event__organizer=self.context['organizer']),
|
||||
)
|
||||
|
||||
if 'customer' in self.context['request'].query_params.getlist('expand'):
|
||||
self.fields['customer'] = CustomerSerializer(read_only=True)
|
||||
else:
|
||||
self.fields['customer'] = serializers.SlugRelatedField(
|
||||
required=False,
|
||||
allow_null=True,
|
||||
slug_field='identifier',
|
||||
queryset=self.context['organizer'].customers.all()
|
||||
)
|
||||
|
||||
def validate(self, data):
|
||||
data = super().validate(data)
|
||||
if 'type' in data and 'identifier' in data:
|
||||
qs = self.context['organizer'].reusable_media.filter(
|
||||
identifier=data['identifier'], type=data['type']
|
||||
)
|
||||
if self.instance:
|
||||
qs = qs.exclude(pk=self.instance.pk)
|
||||
if qs.exists():
|
||||
raise ValidationError(
|
||||
{'identifier': _('A medium with the same identifier and type already exists in your organizer account.')}
|
||||
)
|
||||
return data
|
||||
|
||||
class Meta:
|
||||
model = ReusableMedium
|
||||
fields = (
|
||||
'id',
|
||||
'created',
|
||||
'updated',
|
||||
'type',
|
||||
'identifier',
|
||||
'active',
|
||||
'expires',
|
||||
'customer',
|
||||
'linked_orderposition',
|
||||
'linked_giftcard',
|
||||
'info',
|
||||
'notes',
|
||||
)
|
||||
|
||||
|
||||
class MediaLookupInputSerializer(serializers.Serializer):
|
||||
type = serializers.CharField(required=True)
|
||||
identifier = serializers.CharField(required=True)
|
||||
@@ -33,6 +33,7 @@ from django.utils.encoding import force_str
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext_lazy
|
||||
from django_countries.fields import Country
|
||||
from django_scopes import scopes_disabled
|
||||
from rest_framework import serializers
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from rest_framework.relations import SlugRelatedField
|
||||
@@ -48,8 +49,8 @@ from pretix.base.decimal import round_decimal
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.models import (
|
||||
CachedFile, Checkin, Customer, Invoice, InvoiceAddress, InvoiceLine, Item,
|
||||
ItemVariation, Order, OrderPosition, Question, QuestionAnswer, Seat,
|
||||
SubEvent, TaxRule, Voucher,
|
||||
ItemVariation, Order, OrderPosition, Question, QuestionAnswer,
|
||||
ReusableMedium, Seat, SubEvent, TaxRule, Voucher,
|
||||
)
|
||||
from pretix.base.models.orders import (
|
||||
BlockedTicketSecret, CartPosition, OrderFee, OrderPayment, OrderRefund,
|
||||
@@ -356,6 +357,9 @@ class PdfDataSerializer(serializers.Field):
|
||||
def to_representation(self, instance: OrderPosition):
|
||||
res = {}
|
||||
|
||||
if 'event' not in self.context:
|
||||
return {}
|
||||
|
||||
ev = instance.subevent or instance.order.event
|
||||
with language(instance.order.locale, instance.order.event.settings.region):
|
||||
# This needs to have some extra performance improvements to avoid creating hundreds of queries when
|
||||
@@ -784,13 +788,15 @@ class OrderPositionCreateSerializer(I18nAwareModelSerializer):
|
||||
required=False, allow_null=True)
|
||||
country = CompatibleCountryField(source='*')
|
||||
requested_valid_from = serializers.DateTimeField(required=False, allow_null=True)
|
||||
use_reusable_medium = serializers.PrimaryKeyRelatedField(queryset=ReusableMedium.objects.none(),
|
||||
required=False, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = OrderPosition
|
||||
fields = ('positionid', 'item', 'variation', 'price', 'attendee_name', 'attendee_name_parts', 'attendee_email',
|
||||
'company', 'street', 'zipcode', 'city', 'country', 'state', 'is_bundled',
|
||||
'secret', 'addon_to', 'subevent', 'answers', 'seat', 'voucher', 'valid_from', 'valid_until',
|
||||
'requested_valid_from')
|
||||
'requested_valid_from', 'use_reusable_medium')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -799,6 +805,9 @@ class OrderPositionCreateSerializer(I18nAwareModelSerializer):
|
||||
v.required = False
|
||||
v.allow_blank = True
|
||||
v.allow_null = True
|
||||
with scopes_disabled():
|
||||
if 'use_reusable_medium' in self.fields:
|
||||
self.fields['use_reusable_medium'].queryset = ReusableMedium.objects.all()
|
||||
|
||||
def validate_secret(self, secret):
|
||||
if secret and OrderPosition.all.filter(order__event=self.context['event'], secret=secret).exists():
|
||||
@@ -807,6 +816,13 @@ class OrderPositionCreateSerializer(I18nAwareModelSerializer):
|
||||
)
|
||||
return secret
|
||||
|
||||
def validate_use_reusable_medium(self, m):
|
||||
if m.organizer_id != self.context['event'].organizer_id:
|
||||
raise ValidationError(
|
||||
'The specified medium does not belong to this organizer.'
|
||||
)
|
||||
return m
|
||||
|
||||
def validate_item(self, item):
|
||||
if item.event != self.context['event']:
|
||||
raise ValidationError(
|
||||
@@ -1264,7 +1280,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
pos_data['attendee_name_parts'] = {
|
||||
'_legacy': attendee_name
|
||||
}
|
||||
pos = OrderPosition(**{k: v for k, v in pos_data.items() if k != 'answers' and k != '_quotas'})
|
||||
pos = OrderPosition(**{k: v for k, v in pos_data.items() if k != 'answers' and k != '_quotas' and k != 'use_reusable_medium'})
|
||||
if simulate:
|
||||
pos.order = order._wrapped
|
||||
else:
|
||||
@@ -1332,6 +1348,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
# Save instances
|
||||
for pos_data in positions_data:
|
||||
answers_data = pos_data.pop('answers', [])
|
||||
use_reusable_medium = pos_data.pop('use_reusable_medium', None)
|
||||
pos = pos_data['__instance']
|
||||
pos._calculate_tax()
|
||||
|
||||
@@ -1370,6 +1387,17 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
answ = pos.answers.create(**answ_data)
|
||||
answ.options.add(*options)
|
||||
|
||||
if use_reusable_medium:
|
||||
use_reusable_medium.linked_orderposition = pos
|
||||
use_reusable_medium.save(update_fields=['linked_orderposition'])
|
||||
use_reusable_medium.log_action(
|
||||
'pretix.reusable_medium.linked_orderposition.changed',
|
||||
data={
|
||||
'by_order': order.code,
|
||||
'linked_orderposition': pos.pk,
|
||||
}
|
||||
)
|
||||
|
||||
if not simulate:
|
||||
for cp in delete_cps:
|
||||
if cp.addon_to_id:
|
||||
|
||||
@@ -183,7 +183,7 @@ class TeamSerializer(serializers.ModelSerializer):
|
||||
'id', 'name', 'all_events', 'limit_events', 'can_create_events', 'can_change_teams',
|
||||
'can_change_organizer_settings', 'can_manage_gift_cards', 'can_change_event_settings',
|
||||
'can_change_items', 'can_view_orders', 'can_change_orders', 'can_view_vouchers',
|
||||
'can_change_vouchers', 'can_checkin_orders', 'can_manage_customers'
|
||||
'can_change_vouchers', 'can_checkin_orders', 'can_manage_customers', 'can_manage_reusable_media'
|
||||
)
|
||||
|
||||
def validate(self, data):
|
||||
@@ -333,6 +333,12 @@ class OrganizerSettingsSerializer(SettingsSerializer):
|
||||
'cookie_consent_dialog_text_secondary',
|
||||
'cookie_consent_dialog_button_yes',
|
||||
'cookie_consent_dialog_button_no',
|
||||
'reusable_media_active',
|
||||
'reusable_media_type_barcode',
|
||||
'reusable_media_type_barcode_identifier_length',
|
||||
'reusable_media_type_nfc_uid',
|
||||
'reusable_media_type_nfc_uid_autocreate_giftcard',
|
||||
'reusable_media_type_nfc_uid_autocreate_giftcard_currency',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
@@ -36,6 +36,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class SettingsSerializer(serializers.Serializer):
|
||||
default_fields = []
|
||||
readonly_fields = []
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.changed_data = []
|
||||
@@ -59,8 +60,13 @@ class SettingsSerializer(serializers.Serializer):
|
||||
f.parent = self
|
||||
self.fields[fname] = f
|
||||
|
||||
def validate(self, attrs):
|
||||
return {k: v for k, v in attrs.items() if k not in self.readonly_fields}
|
||||
|
||||
def update(self, instance: HierarkeyProxy, validated_data):
|
||||
for attr, value in validated_data.items():
|
||||
if attr in self.readonly_fields:
|
||||
continue
|
||||
if isinstance(value, FieldFile):
|
||||
# Delete old file
|
||||
fname = instance.get(attr, as_type=File)
|
||||
|
||||
@@ -42,9 +42,9 @@ from rest_framework import routers
|
||||
from pretix.api.views import cart
|
||||
|
||||
from .views import (
|
||||
checkin, device, discount, event, exporters, idempotency, item, oauth,
|
||||
order, organizer, shredders, upload, user, version, voucher, waitinglist,
|
||||
webhooks,
|
||||
checkin, device, discount, event, exporters, idempotency, item, media,
|
||||
oauth, order, organizer, shredders, upload, user, version, voucher,
|
||||
waitinglist, webhooks,
|
||||
)
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
@@ -59,6 +59,7 @@ orga_router.register(r'giftcards', organizer.GiftCardViewSet)
|
||||
orga_router.register(r'customers', organizer.CustomerViewSet)
|
||||
orga_router.register(r'memberships', organizer.MembershipViewSet)
|
||||
orga_router.register(r'membershiptypes', organizer.MembershipTypeViewSet)
|
||||
orga_router.register(r'reusablemedia', media.ReusableMediaViewSet)
|
||||
orga_router.register(r'teams', organizer.TeamViewSet)
|
||||
orga_router.register(r'devices', organizer.DeviceViewSet)
|
||||
orga_router.register(r'exporters', exporters.OrganizerExportersViewSet, basename='exporters')
|
||||
|
||||
+105
-89
@@ -59,7 +59,7 @@ from pretix.api.views.order import OrderPositionFilter
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.models import (
|
||||
CachedFile, Checkin, CheckinList, Device, Event, Order, OrderPosition,
|
||||
Question, RevokedTicketSecret, TeamAPIToken,
|
||||
Question, ReusableMedium, RevokedTicketSecret, TeamAPIToken,
|
||||
)
|
||||
from pretix.base.services.checkin import (
|
||||
CheckInError, RequiredQuestionsError, SQLLogic, perform_checkin,
|
||||
@@ -396,7 +396,7 @@ def _checkin_list_position_queryset(checkinlists, ignore_status=False, ignore_pr
|
||||
|
||||
def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force, checkin_type, ignore_unpaid, nonce,
|
||||
untrusted_input, user, auth, expand, pdf_data, request, questions_supported, canceled_supported,
|
||||
legacy_url_support=False):
|
||||
source_type='barcode', legacy_url_support=False):
|
||||
if not checkinlists:
|
||||
raise ValidationError('No check-in list passed.')
|
||||
|
||||
@@ -422,6 +422,7 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
|
||||
common_checkin_args = dict(
|
||||
raw_barcode=raw_barcode,
|
||||
raw_source_type=source_type,
|
||||
type=checkin_type,
|
||||
list=checkinlists[0],
|
||||
datetime=datetime,
|
||||
@@ -433,7 +434,7 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
raw_barcode_for_checkin = None
|
||||
from_revoked_secret = False
|
||||
|
||||
# 1. Gather a list of positions that could be the one we looking fore, either from their ID, secret or
|
||||
# 1. Gather a list of positions that could be the one we looking for, either from their ID, secret or
|
||||
# parent secret
|
||||
queryset = _checkin_list_position_queryset(checkinlists, pdf_data=pdf_data, ignore_status=True, ignore_products=True).order_by(
|
||||
F('addon_to').asc(nulls_first=True)
|
||||
@@ -457,98 +458,111 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
|
||||
# 2. Handle the "nothing found" case: Either it's really a bogus secret that we don't know (-> error), or it
|
||||
# might be a revoked one that we actually know (-> error, but with better error message and logging and
|
||||
# with respecting the force option).
|
||||
# with respecting the force option), or it's a reusable medium (-> proceed with that)
|
||||
if not op_candidates:
|
||||
revoked_matches = list(RevokedTicketSecret.objects.filter(event_id__in=list_by_event.keys(), secret=raw_barcode))
|
||||
if len(revoked_matches) == 0:
|
||||
checkinlists[0].event.log_action('pretix.event.checkin.unknown', data={
|
||||
'datetime': datetime,
|
||||
'type': checkin_type,
|
||||
'list': checkinlists[0].pk,
|
||||
'barcode': raw_barcode,
|
||||
'searched_lists': [cl.pk for cl in checkinlists]
|
||||
}, user=user, auth=auth)
|
||||
try:
|
||||
media = ReusableMedium.objects.select_related('linked_orderposition').active().get(
|
||||
organizer_id=checkinlists[0].event.organizer_id,
|
||||
type=source_type,
|
||||
identifier=raw_barcode,
|
||||
linked_orderposition__isnull=False,
|
||||
)
|
||||
raw_barcode_for_checkin = raw_barcode
|
||||
except ReusableMedium.DoesNotExist:
|
||||
revoked_matches = list(
|
||||
RevokedTicketSecret.objects.filter(event_id__in=list_by_event.keys(), secret=raw_barcode))
|
||||
if len(revoked_matches) == 0:
|
||||
checkinlists[0].event.log_action('pretix.event.checkin.unknown', data={
|
||||
'datetime': datetime,
|
||||
'type': checkin_type,
|
||||
'list': checkinlists[0].pk,
|
||||
'barcode': raw_barcode,
|
||||
'searched_lists': [cl.pk for cl in checkinlists]
|
||||
}, user=user, auth=auth)
|
||||
|
||||
for cl in checkinlists:
|
||||
for k, s in cl.event.ticket_secret_generators.items():
|
||||
for cl in checkinlists:
|
||||
for k, s in cl.event.ticket_secret_generators.items():
|
||||
try:
|
||||
parsed = s.parse_secret(raw_barcode)
|
||||
common_checkin_args.update({
|
||||
'raw_item': parsed.item,
|
||||
'raw_variation': parsed.variation,
|
||||
'raw_subevent': parsed.subevent,
|
||||
})
|
||||
except:
|
||||
pass
|
||||
|
||||
Checkin.objects.create(
|
||||
position=None,
|
||||
successful=False,
|
||||
error_reason=Checkin.REASON_INVALID,
|
||||
**common_checkin_args,
|
||||
)
|
||||
|
||||
if force and legacy_url_support and isinstance(auth, Device):
|
||||
# There was a bug in libpretixsync: If you scanned a ticket in offline mode that was
|
||||
# valid at the time but no longer exists at time of upload, the device would retry to
|
||||
# upload the same scan over and over again. Since we can't update all devices quickly,
|
||||
# here's a dirty workaround to make it stop.
|
||||
try:
|
||||
parsed = s.parse_secret(raw_barcode)
|
||||
common_checkin_args.update({
|
||||
'raw_item': parsed.item,
|
||||
'raw_variation': parsed.variation,
|
||||
'raw_subevent': parsed.subevent,
|
||||
})
|
||||
except:
|
||||
brand = auth.software_brand
|
||||
ver = parse(auth.software_version)
|
||||
legacy_mode = (
|
||||
(brand == 'pretixSCANPROXY' and ver < parse('0.0.3')) or
|
||||
(brand == 'pretixSCAN Android' and ver < parse('1.11.2')) or
|
||||
(brand == 'pretixSCAN' and ver < parse('1.11.2'))
|
||||
)
|
||||
if legacy_mode:
|
||||
return Response({
|
||||
'status': 'error',
|
||||
'reason': Checkin.REASON_ALREADY_REDEEMED,
|
||||
'reason_explanation': None,
|
||||
'require_attention': False,
|
||||
'__warning': 'Compatibility hack active due to detected old pretixSCAN version',
|
||||
}, status=400)
|
||||
except: # we don't care e.g. about invalid version numbers
|
||||
pass
|
||||
|
||||
Checkin.objects.create(
|
||||
position=None,
|
||||
successful=False,
|
||||
error_reason=Checkin.REASON_INVALID,
|
||||
**common_checkin_args,
|
||||
)
|
||||
|
||||
if force and legacy_url_support and isinstance(auth, Device):
|
||||
# There was a bug in libpretixsync: If you scanned a ticket in offline mode that was
|
||||
# valid at the time but no longer exists at time of upload, the device would retry to
|
||||
# upload the same scan over and over again. Since we can't update all devices quickly,
|
||||
# here's a dirty workaround to make it stop.
|
||||
try:
|
||||
brand = auth.software_brand
|
||||
ver = parse(auth.software_version)
|
||||
legacy_mode = (
|
||||
(brand == 'pretixSCANPROXY' and ver < parse('0.0.3')) or
|
||||
(brand == 'pretixSCAN Android' and ver < parse('1.11.2')) or
|
||||
(brand == 'pretixSCAN' and ver < parse('1.11.2'))
|
||||
)
|
||||
if legacy_mode:
|
||||
return Response({
|
||||
'status': 'error',
|
||||
'reason': Checkin.REASON_ALREADY_REDEEMED,
|
||||
'reason_explanation': None,
|
||||
'require_attention': False,
|
||||
'__warning': 'Compatibility hack active due to detected old pretixSCAN version',
|
||||
}, status=400)
|
||||
except: # we don't care e.g. about invalid version numbers
|
||||
pass
|
||||
|
||||
return Response({
|
||||
'detail': 'Not found.', # for backwards compatibility
|
||||
'status': 'error',
|
||||
'reason': Checkin.REASON_INVALID,
|
||||
'reason_explanation': None,
|
||||
'require_attention': False,
|
||||
'list': MiniCheckinListSerializer(checkinlists[0]).data,
|
||||
}, status=404)
|
||||
elif revoked_matches and force:
|
||||
op_candidates = [revoked_matches[0].position]
|
||||
if list_by_event[revoked_matches[0].event_id].addon_match:
|
||||
op_candidates += list(revoked_matches[0].position.addons.all())
|
||||
raw_barcode_for_checkin = raw_barcode
|
||||
from_revoked_secret = True
|
||||
return Response({
|
||||
'detail': 'Not found.', # for backwards compatibility
|
||||
'status': 'error',
|
||||
'reason': Checkin.REASON_INVALID,
|
||||
'reason_explanation': None,
|
||||
'require_attention': False,
|
||||
'list': MiniCheckinListSerializer(checkinlists[0]).data,
|
||||
}, status=404)
|
||||
elif revoked_matches and force:
|
||||
op_candidates = [revoked_matches[0].position]
|
||||
if list_by_event[revoked_matches[0].event_id].addon_match:
|
||||
op_candidates += list(revoked_matches[0].position.addons.all())
|
||||
raw_barcode_for_checkin = raw_barcode_for_checkin or raw_barcode
|
||||
from_revoked_secret = True
|
||||
else:
|
||||
op = revoked_matches[0].position
|
||||
op.order.log_action('pretix.event.checkin.revoked', data={
|
||||
'datetime': datetime,
|
||||
'type': checkin_type,
|
||||
'list': list_by_event[revoked_matches[0].event_id].pk,
|
||||
'barcode': raw_barcode
|
||||
}, user=user, auth=auth)
|
||||
common_checkin_args['list'] = list_by_event[revoked_matches[0].event_id]
|
||||
Checkin.objects.create(
|
||||
position=op,
|
||||
successful=False,
|
||||
error_reason=Checkin.REASON_REVOKED,
|
||||
**common_checkin_args
|
||||
)
|
||||
return Response({
|
||||
'status': 'error',
|
||||
'reason': Checkin.REASON_REVOKED,
|
||||
'reason_explanation': None,
|
||||
'require_attention': False,
|
||||
'position': CheckinListOrderPositionSerializer(op, context=_make_context(context, revoked_matches[
|
||||
0].event)).data,
|
||||
'list': MiniCheckinListSerializer(list_by_event[revoked_matches[0].event_id]).data,
|
||||
}, status=400)
|
||||
else:
|
||||
op = revoked_matches[0].position
|
||||
op.order.log_action('pretix.event.checkin.revoked', data={
|
||||
'datetime': datetime,
|
||||
'type': checkin_type,
|
||||
'list': list_by_event[revoked_matches[0].event_id].pk,
|
||||
'barcode': raw_barcode
|
||||
}, user=user, auth=auth)
|
||||
common_checkin_args['list'] = list_by_event[revoked_matches[0].event_id]
|
||||
Checkin.objects.create(
|
||||
position=op,
|
||||
successful=False,
|
||||
error_reason=Checkin.REASON_REVOKED,
|
||||
**common_checkin_args
|
||||
)
|
||||
return Response({
|
||||
'status': 'error',
|
||||
'reason': Checkin.REASON_REVOKED,
|
||||
'reason_explanation': None,
|
||||
'require_attention': False,
|
||||
'position': CheckinListOrderPositionSerializer(op, context=_make_context(context, revoked_matches[0].event)).data,
|
||||
'list': MiniCheckinListSerializer(list_by_event[revoked_matches[0].event_id]).data,
|
||||
}, status=400)
|
||||
op_candidates = [media.linked_orderposition] + list(media.linked_orderposition.addons.all())
|
||||
|
||||
# 3. Handle the "multiple options found" case: Except for the unlikely case of a secret being also a valid primary
|
||||
# key on the same list, we're probably dealing with the ``addon_match`` case here and need to figure out
|
||||
@@ -634,6 +648,7 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
auth=auth,
|
||||
type=checkin_type,
|
||||
raw_barcode=raw_barcode_for_checkin,
|
||||
raw_source_type=source_type,
|
||||
from_revoked_secret=from_revoked_secret,
|
||||
)
|
||||
except RequiredQuestionsError as e:
|
||||
@@ -812,6 +827,7 @@ class CheckinRPCRedeemView(views.APIView):
|
||||
return _redeem_process(
|
||||
checkinlists=s.validated_data['lists'],
|
||||
raw_barcode=s.validated_data['secret'],
|
||||
source_type=s.validated_data['source_type'],
|
||||
answers_data=s.validated_data.get('answers'),
|
||||
datetime=s.validated_data.get('datetime') or now(),
|
||||
force=s.validated_data['force'],
|
||||
|
||||
@@ -542,7 +542,8 @@ class EventSettingsView(views.APIView):
|
||||
fname: {
|
||||
'value': s.data[fname],
|
||||
'label': getattr(field, '_label', fname),
|
||||
'help_text': getattr(field, '_help_text', None)
|
||||
'help_text': getattr(field, '_help_text', None),
|
||||
'readonly': fname in s.readonly_fields,
|
||||
} for fname, field in s.fields.items()
|
||||
})
|
||||
return Response(s.data)
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
#
|
||||
# This file is part of pretix (Community Edition).
|
||||
#
|
||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||
#
|
||||
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
|
||||
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
|
||||
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
|
||||
# this file, see <https://pretix.eu/about/en/license>.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
from decimal import Decimal
|
||||
|
||||
import django_filters
|
||||
from django.db import transaction
|
||||
from django.db.models import OuterRef, Prefetch, Subquery, Sum
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.utils.timezone import now
|
||||
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
|
||||
from django_scopes import scopes_disabled
|
||||
from rest_framework import serializers, viewsets
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import MethodNotAllowed
|
||||
from rest_framework.filters import OrderingFilter
|
||||
from rest_framework.response import Response
|
||||
|
||||
from pretix.api.serializers.media import (
|
||||
MediaLookupInputSerializer, ReusableMediaSerializer,
|
||||
)
|
||||
from pretix.base.media import MEDIA_TYPES
|
||||
from pretix.base.models import (
|
||||
Checkin, GiftCard, GiftCardTransaction, OrderPosition, ReusableMedium,
|
||||
)
|
||||
from pretix.helpers import OF_SELF
|
||||
from pretix.helpers.dicts import merge_dicts
|
||||
|
||||
with scopes_disabled():
|
||||
class ReusableMediumFilter(FilterSet):
|
||||
identifier = django_filters.CharFilter(field_name='identifier')
|
||||
type = django_filters.CharFilter(field_name='type')
|
||||
customer = django_filters.CharFilter(field_name='customer__identifier')
|
||||
updated_since = django_filters.IsoDateTimeFilter(field_name='updated', lookup_expr='gte')
|
||||
created_since = django_filters.IsoDateTimeFilter(field_name='created', lookup_expr='gte')
|
||||
|
||||
class Meta:
|
||||
model = ReusableMedium
|
||||
fields = ['identifier', 'type', 'active', 'customer', 'linked_orderposition', 'linked_giftcard']
|
||||
|
||||
|
||||
class ReusableMediaViewSet(viewsets.ModelViewSet):
|
||||
serializer_class = ReusableMediaSerializer
|
||||
queryset = ReusableMedium.objects.none()
|
||||
permission = 'can_manage_reusable_media'
|
||||
write_permission = 'can_manage_reusable_media'
|
||||
filter_backends = (DjangoFilterBackend, OrderingFilter)
|
||||
ordering = ('-updated', '-id')
|
||||
ordering_fields = ('created', 'updated', 'identifier', 'type', 'id')
|
||||
filterset_class = ReusableMediumFilter
|
||||
|
||||
def get_queryset(self):
|
||||
s = GiftCardTransaction.objects.filter(
|
||||
card=OuterRef('pk')
|
||||
).order_by().values('card').annotate(s=Sum('value')).values('s')
|
||||
return self.request.organizer.reusable_media.prefetch_related(
|
||||
Prefetch(
|
||||
'linked_orderposition',
|
||||
queryset=OrderPosition.objects.select_related(
|
||||
'order', 'order__event', 'order__event__organizer', 'seat',
|
||||
).prefetch_related(
|
||||
Prefetch('checkins', queryset=Checkin.objects.all()),
|
||||
'answers', 'answers__options', 'answers__question',
|
||||
)
|
||||
),
|
||||
Prefetch(
|
||||
'linked_giftcard',
|
||||
queryset=GiftCard.objects.annotate(
|
||||
cached_value=Coalesce(Subquery(s), Decimal('0.00'))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def get_serializer_context(self):
|
||||
ctx = super().get_serializer_context()
|
||||
ctx['organizer'] = self.request.organizer
|
||||
return ctx
|
||||
|
||||
@transaction.atomic()
|
||||
def perform_create(self, serializer):
|
||||
inst = serializer.save(organizer=self.request.organizer)
|
||||
inst.log_action(
|
||||
'pretix.reusable_medium.created',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data=merge_dicts(self.request.data, {'id': inst.pk})
|
||||
)
|
||||
|
||||
@transaction.atomic()
|
||||
def perform_update(self, serializer):
|
||||
ReusableMedium.objects.select_for_update(of=OF_SELF).get(pk=self.get_object().pk)
|
||||
inst = serializer.save(identifier=serializer.instance.identifier, type=serializer.instance.type)
|
||||
inst.log_action(
|
||||
'pretix.reusable_medium.changed',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data=self.request.data,
|
||||
)
|
||||
return inst
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
raise MethodNotAllowed("Media cannot be deleted.")
|
||||
|
||||
@action(methods=["POST"], detail=False)
|
||||
def lookup(self, request, *args, **kwargs):
|
||||
s = MediaLookupInputSerializer(
|
||||
data=request.data,
|
||||
)
|
||||
s.is_valid(raise_exception=True)
|
||||
|
||||
try:
|
||||
m = ReusableMedium.objects.get(
|
||||
type=s.validated_data["type"],
|
||||
identifier=s.validated_data["identifier"],
|
||||
organizer=request.organizer,
|
||||
)
|
||||
s = self.get_serializer(m)
|
||||
return Response({"result": s.data})
|
||||
except ReusableMedium.DoesNotExist:
|
||||
mt = MEDIA_TYPES.get(s.validated_data["type"])
|
||||
if mt:
|
||||
m = mt.handle_unknown(request.organizer, s.validated_data["identifier"], request.user, request.auth)
|
||||
if m:
|
||||
s = self.get_serializer(m)
|
||||
return Response({"result": s.data})
|
||||
|
||||
return Response({"result": None})
|
||||
|
||||
@scopes_disabled() # we are sure enough that get_queryset() is correct, so we save some perforamnce
|
||||
def list(self, request, **kwargs):
|
||||
date = serializers.DateTimeField().to_representation(now())
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
|
||||
page = self.paginate_queryset(queryset)
|
||||
if page is not None:
|
||||
serializer = self.get_serializer(page, many=True)
|
||||
resp = self.get_paginated_response(serializer.data)
|
||||
resp['X-Page-Generated'] = date
|
||||
return resp
|
||||
|
||||
serializer = self.get_serializer(queryset, many=True)
|
||||
return Response(serializer.data, headers={'X-Page-Generated': date})
|
||||
@@ -244,7 +244,8 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
Prefetch('subevent', queryset=self.request.event.subevents.prefetch_related(
|
||||
Prefetch('meta_values', to_attr='meta_values_cached', queryset=SubEventMetaValue.objects.select_related('property'))
|
||||
)),
|
||||
Prefetch('addons', opq.select_related('item', 'variation', 'seat'))
|
||||
Prefetch('addons', opq.select_related('item', 'variation', 'seat')),
|
||||
'linked_media',
|
||||
).select_related('seat', 'addon_to', 'addon_to__seat')
|
||||
)
|
||||
else:
|
||||
@@ -639,13 +640,11 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
raise ValidationError(_('One of the selected products is not available in the selected country.'))
|
||||
send_mail = serializer._send_mail
|
||||
order = serializer.instance
|
||||
|
||||
if not order.pk:
|
||||
# Simulation
|
||||
# Simulation -- exit here
|
||||
serializer = SimulatedOrderSerializer(order, context=serializer.context)
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
else:
|
||||
prefetch_related_objects([order], self._positions_prefetch(request))
|
||||
serializer = OrderSerializer(order, context=serializer.context)
|
||||
|
||||
order.log_action(
|
||||
'pretix.event.order.placed',
|
||||
@@ -679,6 +678,10 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
if gen_invoice:
|
||||
invoice = generate_invoice(order, trigger_pdf=True)
|
||||
|
||||
# Refresh serializer only after running signals
|
||||
prefetch_related_objects([order], self._positions_prefetch(request))
|
||||
serializer = OrderSerializer(order, context=serializer.context)
|
||||
|
||||
if send_mail:
|
||||
free_flow = (
|
||||
payment and order.total == Decimal('0.00') and order.status == Order.STATUS_PAID and
|
||||
@@ -1005,6 +1008,7 @@ class OrderPositionViewSet(viewsets.ModelViewSet):
|
||||
Prefetch('meta_values', to_attr='meta_values_cached',
|
||||
queryset=SubEventMetaValue.objects.select_related('property'))
|
||||
)),
|
||||
'linked_media',
|
||||
Prefetch('order', self.request.event.orders.select_related('invoice_address').prefetch_related(
|
||||
Prefetch(
|
||||
'positions',
|
||||
|
||||
@@ -457,7 +457,8 @@ class OrganizerSettingsView(views.APIView):
|
||||
fname: {
|
||||
'value': s.data[fname],
|
||||
'label': getattr(field, '_label', fname),
|
||||
'help_text': getattr(field, '_help_text', None)
|
||||
'help_text': getattr(field, '_help_text', None),
|
||||
'readonly': fname in s.readonly_fields,
|
||||
} for fname, field in s.fields.items()
|
||||
})
|
||||
return Response(s.data)
|
||||
|
||||
@@ -256,6 +256,10 @@ def register_default_webhook_events(sender, **kwargs):
|
||||
'pretix.event.order.refund.failed',
|
||||
_('Refund of payment failed'),
|
||||
),
|
||||
ParametrizedOrderWebhookEvent(
|
||||
'pretix.event.order.payment.confirmed',
|
||||
_('Payment confirmed'),
|
||||
),
|
||||
ParametrizedOrderWebhookEvent(
|
||||
'pretix.event.order.approved',
|
||||
_('Order approved'),
|
||||
|
||||
+11
-11
@@ -35,16 +35,14 @@ from django.dispatch import receiver
|
||||
from django.template.loader import get_template
|
||||
from django.utils.formats import date_format
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import (
|
||||
get_language, gettext_lazy as _, pgettext_lazy,
|
||||
)
|
||||
from django.utils.translation import get_language, gettext_lazy as _
|
||||
|
||||
from pretix.base.i18n import (
|
||||
LazyCurrencyNumber, LazyDate, LazyExpiresDate, LazyNumber,
|
||||
)
|
||||
from pretix.base.models import Event
|
||||
from pretix.base.reldate import RelativeDateWrapper
|
||||
from pretix.base.settings import PERSON_NAME_SCHEMES
|
||||
from pretix.base.settings import PERSON_NAME_SCHEMES, get_name_parts_localized
|
||||
from pretix.base.signals import (
|
||||
register_html_mail_renderers, register_mail_placeholders,
|
||||
)
|
||||
@@ -663,6 +661,11 @@ def base_placeholders(sender, **kwargs):
|
||||
else:
|
||||
concatenation_for_salutation = name_scheme["concatenation"]
|
||||
|
||||
ph.append(SimpleFunctionalMailTextPlaceholder(
|
||||
"name_for_salutation", ["waiting_list_entry"],
|
||||
lambda waiting_list_entry: concatenation_for_salutation(waiting_list_entry.name_parts),
|
||||
_("Mr Doe"),
|
||||
))
|
||||
ph.append(SimpleFunctionalMailTextPlaceholder(
|
||||
"name_for_salutation", ["position_or_address"],
|
||||
lambda position_or_address: concatenation_for_salutation(get_best_name(position_or_address, parts=True)),
|
||||
@@ -672,6 +675,10 @@ def base_placeholders(sender, **kwargs):
|
||||
for f, l, w in name_scheme['fields']:
|
||||
if f == 'full_name':
|
||||
continue
|
||||
ph.append(SimpleFunctionalMailTextPlaceholder(
|
||||
'name_%s' % f, ['waiting_list_entry'], lambda waiting_list_entry, f=f: get_name_parts_localized(waiting_list_entry.name_parts, f),
|
||||
name_scheme['sample'][f]
|
||||
))
|
||||
ph.append(SimpleFunctionalMailTextPlaceholder(
|
||||
'attendee_name_%s' % f, ['position'], lambda position, f=f: get_name_parts_localized(position.attendee_name_parts, f),
|
||||
name_scheme['sample'][f]
|
||||
@@ -693,10 +700,3 @@ def base_placeholders(sender, **kwargs):
|
||||
))
|
||||
|
||||
return ph
|
||||
|
||||
|
||||
def get_name_parts_localized(name_parts, key):
|
||||
value = name_parts.get(key, "")
|
||||
if key == "salutation":
|
||||
return pgettext_lazy("person_name_salutation", value)
|
||||
return value
|
||||
|
||||
@@ -56,7 +56,7 @@ from pretix.base.models import (
|
||||
)
|
||||
from pretix.base.models.orders import OrderFee, OrderPayment, OrderRefund
|
||||
from pretix.base.services.quotas import QuotaAvailability
|
||||
from pretix.base.settings import PERSON_NAME_SCHEMES
|
||||
from pretix.base.settings import PERSON_NAME_SCHEMES, get_name_parts_localized
|
||||
|
||||
from ...control.forms.filter import get_all_payment_providers
|
||||
from ...helpers import GroupConcat
|
||||
@@ -340,7 +340,7 @@ class OrderListExporter(MultiSheetListExporter):
|
||||
if name_scheme and len(name_scheme['fields']) > 1:
|
||||
for k, label, w in name_scheme['fields']:
|
||||
row.append(
|
||||
order.invoice_address.name_parts.get(k, '')
|
||||
get_name_parts_localized(order.invoice_address.name_parts, k)
|
||||
)
|
||||
row += [
|
||||
order.invoice_address.street,
|
||||
@@ -477,7 +477,7 @@ class OrderListExporter(MultiSheetListExporter):
|
||||
if name_scheme and len(name_scheme['fields']) > 1:
|
||||
for k, label, w in name_scheme['fields']:
|
||||
row.append(
|
||||
order.invoice_address.name_parts.get(k, '')
|
||||
get_name_parts_localized(order.invoice_address.name_parts, k)
|
||||
)
|
||||
row += [
|
||||
order.invoice_address.street,
|
||||
@@ -660,7 +660,7 @@ class OrderListExporter(MultiSheetListExporter):
|
||||
if name_scheme and len(name_scheme['fields']) > 1:
|
||||
for k, label, w in name_scheme['fields']:
|
||||
row.append(
|
||||
op.attendee_name_parts.get(k, '')
|
||||
get_name_parts_localized(op.attendee_name_parts, k)
|
||||
)
|
||||
row += [
|
||||
op.attendee_email,
|
||||
@@ -721,7 +721,7 @@ class OrderListExporter(MultiSheetListExporter):
|
||||
if name_scheme and len(name_scheme['fields']) > 1:
|
||||
for k, label, w in name_scheme['fields']:
|
||||
row.append(
|
||||
order.invoice_address.name_parts.get(k, '')
|
||||
get_name_parts_localized(order.invoice_address.name_parts, k)
|
||||
)
|
||||
row += [
|
||||
order.invoice_address.street,
|
||||
|
||||
@@ -747,12 +747,14 @@ class BaseQuestionsForm(forms.Form):
|
||||
elif q.type == Question.TYPE_STRING:
|
||||
field = forms.CharField(
|
||||
label=label, required=required,
|
||||
max_length=q.valid_string_length_max,
|
||||
help_text=help_text,
|
||||
initial=initial.answer if initial else None,
|
||||
)
|
||||
elif q.type == Question.TYPE_TEXT:
|
||||
field = forms.CharField(
|
||||
label=label, required=required,
|
||||
max_length=q.valid_string_length_max,
|
||||
help_text=help_text,
|
||||
widget=forms.Textarea,
|
||||
initial=initial.answer if initial else None,
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
#
|
||||
# This file is part of pretix (Community Edition).
|
||||
#
|
||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||
#
|
||||
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
|
||||
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
|
||||
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
|
||||
# this file, see <https://pretix.eu/about/en/license>.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
from django.db import transaction
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class BaseMediaType:
|
||||
medium_created_by_server = False
|
||||
supports_orderposition = False
|
||||
supports_giftcard = False
|
||||
|
||||
@property
|
||||
def identifier(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
@property
|
||||
def verbose_name(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def generate_identifier(self, organizer):
|
||||
if self.medium_created_by_server:
|
||||
raise NotImplementedError()
|
||||
else:
|
||||
raise ValueError("Media type does not allow to generate identifier")
|
||||
|
||||
def is_active(self, organizer):
|
||||
return organizer.settings.get(f'reusable_media_type_{self.identifier}', as_type=bool, default=False)
|
||||
|
||||
def handle_unknown(self, organizer, identifier, user, auth):
|
||||
pass
|
||||
|
||||
def __str__(self):
|
||||
return str(self.verbose_name)
|
||||
|
||||
|
||||
class BarcodePlainMediaType(BaseMediaType):
|
||||
identifier = 'barcode'
|
||||
verbose_name = _('Barcode / QR-Code')
|
||||
medium_created_by_server = True
|
||||
supports_giftcard = False
|
||||
supports_orderposition = True
|
||||
|
||||
def generate_identifier(self, organizer):
|
||||
return get_random_string(
|
||||
length=organizer.settings.reusable_media_type_barcode_identifier_length,
|
||||
# Exclude o,0,1,i to avoid confusion with bad fonts/printers
|
||||
# We use upper case to make collisions with ticket secrets less likely
|
||||
allowed_chars='ABCDEFGHJKLMNPQRSTUVWXYZ23456789'
|
||||
)
|
||||
|
||||
|
||||
class NfcUidMediaType(BaseMediaType):
|
||||
identifier = 'nfc_uid'
|
||||
verbose_name = _('NFC UID-based')
|
||||
medium_created_by_server = False
|
||||
supports_giftcard = True
|
||||
supports_orderposition = False
|
||||
|
||||
def handle_unknown(self, organizer, identifier, user, auth):
|
||||
from pretix.base.models import GiftCard, ReusableMedium
|
||||
|
||||
if organizer.settings.get(f'reusable_media_type_{self.identifier}_autocreate_giftcard', as_type=bool):
|
||||
if identifier.startswith("08"):
|
||||
# Don't create gift cards for NFC UIDs that start with 08, which represents NFC cards that issue random
|
||||
# UIDs on every read, so they won't be useful.
|
||||
return
|
||||
with transaction.atomic():
|
||||
gc = GiftCard.objects.create(
|
||||
issuer=organizer,
|
||||
expires=organizer.default_gift_card_expiry,
|
||||
currency=organizer.settings.get(f'reusable_media_type_{self.identifier}_autocreate_giftcard_currency'),
|
||||
)
|
||||
m = ReusableMedium.objects.create(
|
||||
type=self.identifier,
|
||||
identifier=identifier,
|
||||
organizer=organizer,
|
||||
active=True,
|
||||
linked_giftcard=gc
|
||||
)
|
||||
m.log_action(
|
||||
'pretix.reusable_medium.created.auto',
|
||||
user=user, auth=auth,
|
||||
)
|
||||
gc.log_action(
|
||||
'pretix.giftcards.created',
|
||||
user=user, auth=auth,
|
||||
)
|
||||
return m
|
||||
|
||||
|
||||
MEDIA_TYPES = {
|
||||
m.identifier: m for m in [
|
||||
BarcodePlainMediaType(),
|
||||
NfcUidMediaType(),
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
# Generated by Django 3.2.18 on 2023-02-20 12:46
|
||||
|
||||
import django.core.serializers.json
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.base
|
||||
|
||||
|
||||
def set_can_manage_reusable_media(apps, schema_editor):
|
||||
Team = apps.get_model('pretixbase', 'Team')
|
||||
Team.objects.filter(can_change_organizer_settings=True).update(can_manage_reusable_media=True)
|
||||
Team.objects.filter(can_change_orders=True, all_events=True).update(can_manage_reusable_media=True)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('pretixbase', '0235_auto_20230316_2023'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='item',
|
||||
name='media_policy',
|
||||
field=models.CharField(max_length=16, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='item',
|
||||
name='media_type',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='team',
|
||||
name='can_manage_reusable_media',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ReusableMedium',
|
||||
fields=[
|
||||
('id', models.BigAutoField(primary_key=True, serialize=False)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('updated', models.DateTimeField(auto_now=True)),
|
||||
('type', models.CharField(max_length=100)),
|
||||
('identifier', models.CharField(max_length=200)),
|
||||
('active', models.BooleanField(default=True)),
|
||||
('expires', models.DateTimeField(blank=True, null=True)),
|
||||
('info', models.JSONField(default=dict)),
|
||||
('notes', models.TextField(null=True, blank=True)),
|
||||
('customer', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name='reusable_media', to='pretixbase.customer')),
|
||||
('linked_giftcard',
|
||||
models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='linked_media',
|
||||
to='pretixbase.giftcard')),
|
||||
('linked_orderposition',
|
||||
models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='linked_media',
|
||||
to='pretixbase.orderposition')),
|
||||
('organizer',
|
||||
models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='reusable_media',
|
||||
to='pretixbase.organizer')),
|
||||
],
|
||||
options={
|
||||
'ordering': ('identifier', 'type', 'organizer'),
|
||||
'unique_together': {('identifier', 'type', 'organizer')},
|
||||
'index_together': {('identifier', 'type', 'organizer'), ('updated', 'id')},
|
||||
},
|
||||
bases=(models.Model, pretix.base.models.base.LoggingMixin),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='checkin',
|
||||
name='raw_source_type',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.RunPython(
|
||||
set_can_manage_reusable_media,
|
||||
migrations.RunPython.noop,
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.18 on 2023-04-05 10:03
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0236_reusable_media'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='question',
|
||||
name='valid_string_length_max',
|
||||
field=models.PositiveIntegerField(null=True),
|
||||
),
|
||||
]
|
||||
@@ -40,6 +40,7 @@ from .items import (
|
||||
SubEventItem, SubEventItemVariation, itempicture_upload_to,
|
||||
)
|
||||
from .log import LogEntry
|
||||
from .media import ReusableMedium
|
||||
from .memberships import Membership, MembershipType
|
||||
from .notifications import NotificationSetting
|
||||
from .orders import (
|
||||
|
||||
@@ -44,6 +44,7 @@ from django.utils.timezone import now
|
||||
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
from django_scopes import ScopedManager, scopes_disabled
|
||||
|
||||
from pretix.base.media import MEDIA_TYPES
|
||||
from pretix.base.models import LoggedModel
|
||||
from pretix.base.models.fields import MultiStringField
|
||||
from pretix.helpers import PostgresWindowFrame
|
||||
@@ -377,6 +378,11 @@ class Checkin(models.Model):
|
||||
# For "raw" scans where we do not know which position they belong to (e.g. scan of signed
|
||||
# barcode that is not in database).
|
||||
raw_barcode = models.TextField(null=True, blank=True)
|
||||
raw_source_type = models.CharField(
|
||||
max_length=100,
|
||||
null=True, blank=True,
|
||||
choices=[(k, v) for k, v in MEDIA_TYPES.items()],
|
||||
)
|
||||
raw_item = models.ForeignKey(
|
||||
'pretixbase.Item',
|
||||
related_name='checkins',
|
||||
|
||||
@@ -142,6 +142,7 @@ class Customer(LoggedModel):
|
||||
self.save()
|
||||
self.all_logentries().update(data={}, shredded=True)
|
||||
self.orders.all().update(customer=None)
|
||||
self.reusable_media.all().update(customer=None)
|
||||
self.memberships.all().update(attendee_name_parts=None)
|
||||
self.attendee_profiles.all().delete()
|
||||
self.invoice_addresses.all().delete()
|
||||
@@ -221,7 +222,7 @@ class Customer(LoggedModel):
|
||||
return salted_hmac(key_salt, payload).hexdigest()
|
||||
|
||||
def get_email_context(self):
|
||||
from pretix.base.email import get_name_parts_localized
|
||||
from pretix.base.settings import get_name_parts_localized
|
||||
ctx = {
|
||||
'name': self.name,
|
||||
'organizer': self.organizer.name,
|
||||
|
||||
@@ -180,7 +180,8 @@ class Device(LoggedModel):
|
||||
'can_view_orders',
|
||||
'can_change_orders',
|
||||
'can_view_vouchers',
|
||||
'can_manage_gift_cards'
|
||||
'can_manage_gift_cards',
|
||||
'can_manage_reusable_media',
|
||||
}
|
||||
|
||||
def get_event_permission_set(self, organizer, event) -> set:
|
||||
|
||||
@@ -45,7 +45,9 @@ import dateutil.parser
|
||||
import pytz
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import MinValueValidator, RegexValidator
|
||||
from django.core.validators import (
|
||||
MaxLengthValidator, MinValueValidator, RegexValidator,
|
||||
)
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
from django.utils import formats
|
||||
@@ -64,6 +66,7 @@ from pretix.base.models.fields import MultiStringField
|
||||
from pretix.base.models.tax import TaxedPrice
|
||||
|
||||
from ...helpers.images import ImageSizeValidator
|
||||
from ..media import MEDIA_TYPES
|
||||
from .event import Event, SubEvent
|
||||
|
||||
|
||||
@@ -368,6 +371,16 @@ class Item(LoggedModel):
|
||||
(VALIDITY_MODE_DYNAMIC, _('Dynamic validity')),
|
||||
)
|
||||
|
||||
MEDIA_POLICY_REUSE = 'reuse'
|
||||
MEDIA_POLICY_NEW = 'new'
|
||||
MEDIA_POLICY_REUSE_OR_NEW = 'reuse_or_new'
|
||||
MEDIA_POLICIES = (
|
||||
(None, _("Don't use re-usable media, use regular one-off tickets")),
|
||||
(MEDIA_POLICY_REUSE, _('Require an existing medium to be re-used')),
|
||||
(MEDIA_POLICY_NEW, _('Require a previously unknown medium to be newly added')),
|
||||
(MEDIA_POLICY_REUSE_OR_NEW, _('Require either an existing or a new medium to be used')),
|
||||
)
|
||||
|
||||
objects = ItemQuerySetManager()
|
||||
|
||||
event = models.ForeignKey(
|
||||
@@ -630,6 +643,29 @@ class Item(LoggedModel):
|
||||
help_text=_('The selected start date may only be this many days in the future.')
|
||||
)
|
||||
|
||||
media_policy = models.CharField(
|
||||
choices=MEDIA_POLICIES,
|
||||
null=True, blank=True, max_length=16,
|
||||
verbose_name=_('Reusable media policy'),
|
||||
help_text=_(
|
||||
'If this product should be stored on a re-usable physical medium, you can attach a physical media policy. '
|
||||
'This is not required for regular tickets, which just use a one-time barcode, but only for products like '
|
||||
'renewable season tickets or re-chargeable gift card wristbands. '
|
||||
'This is an advanced feature that also requires specific configuration of ticketing and printing settings.'
|
||||
)
|
||||
)
|
||||
media_type = models.CharField(
|
||||
max_length=100,
|
||||
null=True, blank=True,
|
||||
choices=[(None, _("Don't use re-usable media, use regular one-off tickets"))] + [(k, v) for k, v in MEDIA_TYPES.items()],
|
||||
verbose_name=_('Reusable media type'),
|
||||
help_text=_(
|
||||
'Select the type of physical medium that should be used for this product. Note that not all media types '
|
||||
'support all types of products, and not all media types are supported across all sales channels or '
|
||||
'check-in processes.'
|
||||
)
|
||||
)
|
||||
|
||||
# !!! Attention: If you add new fields here, also add them to the copying code in
|
||||
# pretix/control/forms/item.py if applicable.
|
||||
|
||||
@@ -801,6 +837,24 @@ class Item(LoggedModel):
|
||||
def has_variations(self):
|
||||
return self.variations.exists()
|
||||
|
||||
@staticmethod
|
||||
def clean_media_settings(event, media_policy, media_type, issue_giftcard):
|
||||
if media_policy:
|
||||
if not media_type:
|
||||
raise ValidationError(_('If you select a reusable media policy, you also need to select a reusable '
|
||||
'media type.'))
|
||||
mt = MEDIA_TYPES[media_type]
|
||||
if not mt.is_active(event.organizer):
|
||||
raise ValidationError(_('The selected media type is not enabled in your organizer settings.'))
|
||||
if not mt.supports_orderposition and not issue_giftcard:
|
||||
raise ValidationError(_('The selected media type does not support usage for tickets currently.'))
|
||||
if not mt.supports_giftcard and issue_giftcard:
|
||||
raise ValidationError(_('The selected media type does not support usage for gift cards currently.'))
|
||||
if issue_giftcard:
|
||||
raise ValidationError(_('You currently cannot create gift cards with a reusable media policy. Instead, '
|
||||
'gift cards for some reusable media types can be created or re-charged directly '
|
||||
'at the POS.'))
|
||||
|
||||
@staticmethod
|
||||
def clean_per_order(min_per_order, max_per_order):
|
||||
if min_per_order is not None and max_per_order is not None:
|
||||
@@ -1488,6 +1542,11 @@ class Question(LoggedModel):
|
||||
valid_datetime_max = models.DateTimeField(null=True, blank=True,
|
||||
verbose_name=_('Maximum value'),
|
||||
help_text=_('Currently not supported in our apps and during check-in'))
|
||||
valid_string_length_max = models.PositiveIntegerField(null=True, blank=True,
|
||||
verbose_name=_('Maximum length'),
|
||||
help_text=_(
|
||||
'Currently not supported in our apps and during check-in'
|
||||
))
|
||||
valid_file_portrait = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name=_('Validate file to be a portrait'),
|
||||
@@ -1634,6 +1693,12 @@ class Question(LoggedModel):
|
||||
return answer
|
||||
else:
|
||||
raise ValidationError(_('Unknown country code.'))
|
||||
elif self.type in (Question.TYPE_STRING, Question.TYPE_TEXT):
|
||||
if self.valid_string_length_max is not None and len(answer) > self.valid_string_length_max:
|
||||
raise ValidationError(MaxLengthValidator.message % {
|
||||
'limit_value': self.valid_string_length_max,
|
||||
'show_value': len(answer)
|
||||
})
|
||||
|
||||
return answer
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
#
|
||||
# This file is part of pretix (Community Edition).
|
||||
#
|
||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||
# Copyright (C) 2020-2021 rami.io GmbH and contributors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||
#
|
||||
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
|
||||
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
|
||||
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
|
||||
# this file, see <https://pretix.eu/about/en/license>.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
from django_scopes import ScopedManager
|
||||
|
||||
from pretix.base.media import MEDIA_TYPES
|
||||
from pretix.base.models import LoggedModel
|
||||
from pretix.base.models.customers import Customer
|
||||
from pretix.base.models.giftcards import GiftCard
|
||||
from pretix.base.models.orders import OrderPosition
|
||||
from pretix.base.models.organizer import Organizer
|
||||
|
||||
|
||||
class ReusableMediumQuerySet(models.QuerySet):
|
||||
|
||||
def active(self):
|
||||
return self.filter(
|
||||
Q(expires__isnull=True) | Q(expires__gte=now()),
|
||||
active=True,
|
||||
)
|
||||
|
||||
|
||||
class ReusableMediumQuerySetManager(ScopedManager(organizer='organizer').__class__):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._queryset_class = ReusableMediumQuerySet
|
||||
|
||||
def active(self):
|
||||
return self.get_queryset().active()
|
||||
|
||||
|
||||
class ReusableMedium(LoggedModel):
|
||||
id = models.BigAutoField(primary_key=True)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
|
||||
organizer = models.ForeignKey(
|
||||
Organizer,
|
||||
related_name='reusable_media',
|
||||
on_delete=models.PROTECT
|
||||
)
|
||||
|
||||
type = models.CharField(
|
||||
verbose_name=pgettext_lazy('reusable_medium', 'Media type'),
|
||||
choices=((k, v) for k, v in MEDIA_TYPES.items()),
|
||||
max_length=100,
|
||||
)
|
||||
identifier = models.CharField(
|
||||
max_length=200,
|
||||
verbose_name=pgettext_lazy('reusable_medium', 'Identifier'),
|
||||
)
|
||||
|
||||
active = models.BooleanField(
|
||||
verbose_name=_('Active'),
|
||||
default=True
|
||||
)
|
||||
expires = models.DateTimeField(
|
||||
verbose_name=_('Expiration date'),
|
||||
null=True, blank=True
|
||||
)
|
||||
|
||||
customer = models.ForeignKey(
|
||||
Customer,
|
||||
null=True, blank=True,
|
||||
related_name='reusable_media',
|
||||
on_delete=models.SET_NULL,
|
||||
verbose_name=_('Customer account'),
|
||||
)
|
||||
linked_orderposition = models.ForeignKey(
|
||||
OrderPosition,
|
||||
null=True, blank=True,
|
||||
related_name='linked_media',
|
||||
on_delete=models.SET_NULL,
|
||||
verbose_name=_('Linked ticket'),
|
||||
)
|
||||
linked_giftcard = models.ForeignKey(
|
||||
GiftCard,
|
||||
null=True, blank=True,
|
||||
related_name='linked_media',
|
||||
on_delete=models.SET_NULL,
|
||||
verbose_name=_('Linked gift card'),
|
||||
)
|
||||
|
||||
info = models.JSONField(
|
||||
default=dict
|
||||
)
|
||||
notes = models.TextField(verbose_name=_('Notes'), null=True, blank=True)
|
||||
|
||||
objects = ReusableMediumQuerySetManager()
|
||||
|
||||
@cached_property
|
||||
def media_type(self):
|
||||
return MEDIA_TYPES[self.type]
|
||||
|
||||
@property
|
||||
def is_expired(self):
|
||||
return self.expires and self.expires > now()
|
||||
|
||||
class Meta:
|
||||
unique_together = (("identifier", "type", "organizer"),)
|
||||
index_together = (("identifier", "type", "organizer"), ("updated", "id"))
|
||||
ordering = "identifier", "type", "organizer"
|
||||
@@ -236,6 +236,8 @@ class Team(LoggedModel):
|
||||
:type can_change_teams: bool
|
||||
:param can_manage_customers: If ``True``, the members can view and change organizer-level customer accounts.
|
||||
:type can_manage_customers: bool
|
||||
:param can_manage_reusable_media: If ``True``, the members can view and change organizer-level reusable media.
|
||||
:type can_manage_reusable_media: bool
|
||||
:param can_change_organizer_settings: If ``True``, the members can change the settings of this organizer account.
|
||||
:type can_change_organizer_settings: bool
|
||||
:param can_change_event_settings: If ``True``, the members can change the settings of the associated events.
|
||||
@@ -277,6 +279,10 @@ class Team(LoggedModel):
|
||||
default=False,
|
||||
verbose_name=_("Can manage customer accounts")
|
||||
)
|
||||
can_manage_reusable_media = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name=_("Can manage reusable media")
|
||||
)
|
||||
can_manage_gift_cards = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name=_("Can manage gift cards")
|
||||
|
||||
+13
-4
@@ -360,7 +360,7 @@ DEFAULT_VARIABLES = OrderedDict((
|
||||
"label": _("List of Add-Ons"),
|
||||
"editor_sample": _("Add-on 1\nAdd-on 2"),
|
||||
"evaluate": lambda op, order, ev: "\n".join([
|
||||
'{} - {}'.format(p.item, p.variation) if p.variation else str(p.item)
|
||||
'{} - {}'.format(p.item.name, p.variation.value) if p.variation else str(p.item.name)
|
||||
for p in (
|
||||
op.addons.all() if 'addons' in getattr(op, '_prefetched_objects_cache', {})
|
||||
else op.addons.select_related('item', 'variation')
|
||||
@@ -455,6 +455,11 @@ DEFAULT_VARIABLES = OrderedDict((
|
||||
"TIME_FORMAT"
|
||||
) if op.valid_until else ""
|
||||
}),
|
||||
("medium_identifier", {
|
||||
"label": _("Reusable Medium ID"),
|
||||
"editor_sample": "ABC1234DEF4567",
|
||||
"evaluate": lambda op, order, ev: op.linked_media.all()[0].identifier if op.linked_media.all() else "",
|
||||
}),
|
||||
("seat", {
|
||||
"label": _("Seat: Full name"),
|
||||
"editor_sample": _("Ground floor, Row 3, Seat 4"),
|
||||
@@ -583,10 +588,11 @@ def variables_from_questions(sender, *args, **kwargs):
|
||||
|
||||
|
||||
def _get_attendee_name_part(key, op, order, ev):
|
||||
name_parts = op.attendee_name_parts or (op.addon_to.attendee_name_parts if op.addon_to else {})
|
||||
if isinstance(key, tuple):
|
||||
parts = [_get_attendee_name_part(c[0], op, order, ev) for c in key if not (c[0] == 'salutation' and op.attendee_name_parts.get(c[0], '') == "Mx")]
|
||||
parts = [_get_attendee_name_part(c[0], op, order, ev) for c in key if not (c[0] == 'salutation' and name_parts.get(c[0], '') == "Mx")]
|
||||
return ' '.join(p for p in parts if p)
|
||||
value = op.attendee_name_parts.get(key, '')
|
||||
value = name_parts.get(key, '')
|
||||
if key == 'salutation':
|
||||
return pgettext('person_name_salutation', value)
|
||||
return value
|
||||
@@ -617,7 +623,7 @@ def get_variables(event):
|
||||
v['attendee_name_for_salutation'] = {
|
||||
'label': _("Attendee name for salutation"),
|
||||
'editor_sample': _("Mr Doe"),
|
||||
'evaluate': lambda op, order, ev: concatenation_for_salutation(op.attendee_name_parts or {})
|
||||
'evaluate': lambda op, order, ev: concatenation_for_salutation(op.attendee_name_parts or (op.addon_to.attendee_name_parts if op.addon_to else {}))
|
||||
}
|
||||
|
||||
for key, label, weight in scheme['fields']:
|
||||
@@ -761,6 +767,9 @@ class Renderer:
|
||||
else:
|
||||
content = self._get_text_content(op, order, o)
|
||||
|
||||
if len(content) == 0:
|
||||
return
|
||||
|
||||
level = 'H'
|
||||
if len(content) > 32:
|
||||
level = 'M'
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the Apache License 2.0 is
|
||||
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under the License.
|
||||
import re
|
||||
import uuid
|
||||
from collections import Counter, defaultdict, namedtuple
|
||||
from datetime import datetime, time, timedelta
|
||||
@@ -38,6 +39,7 @@ from decimal import Decimal
|
||||
from typing import List, Optional
|
||||
|
||||
from celery.exceptions import MaxRetriesExceededError
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import DatabaseError, transaction
|
||||
from django.db.models import Count, Exists, IntegerField, OuterRef, Q, Value
|
||||
@@ -50,6 +52,7 @@ from django_scopes import scopes_disabled
|
||||
|
||||
from pretix.base.channels import get_all_sales_channels
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.media import MEDIA_TYPES
|
||||
from pretix.base.models import (
|
||||
CartPosition, Event, InvoiceAddress, Item, ItemVariation, Seat,
|
||||
SeatCategoryMapping, Voucher,
|
||||
@@ -135,6 +138,7 @@ error_messages = {
|
||||
'some_subevent_ended': gettext_lazy(
|
||||
'The booking period for one of the events in your cart has ended. The affected '
|
||||
'positions have been removed from your cart.'),
|
||||
'price_not_a_number': gettext_lazy('The entered price is not a number.'),
|
||||
'price_too_high': gettext_lazy('The entered price is to high.'),
|
||||
'voucher_invalid': gettext_lazy('This voucher code is not known in our database.'),
|
||||
'voucher_min_usages': gettext_lazy(
|
||||
@@ -196,6 +200,8 @@ error_messages = {
|
||||
'seat_multiple': gettext_lazy('You can not select the same seat multiple times.'),
|
||||
'gift_card': gettext_lazy("You entered a gift card instead of a voucher. Gift cards can be entered later on when you're asked for your payment details."),
|
||||
'country_blocked': gettext_lazy('One of the selected products is not available in the selected country.'),
|
||||
'media_usage_not_implemented': gettext_lazy('The configuration of this product requires mapping to a physical '
|
||||
'medium, which is currently not available online.'),
|
||||
}
|
||||
|
||||
|
||||
@@ -391,6 +397,13 @@ class CartManager:
|
||||
if not op.item.is_available() or (op.variation and not op.variation.is_available()):
|
||||
raise CartError(error_messages['unavailable'])
|
||||
|
||||
if op.item.media_policy in (Item.MEDIA_POLICY_NEW, Item.MEDIA_POLICY_REUSE_OR_NEW):
|
||||
mt = MEDIA_TYPES[op.item.media_type]
|
||||
if not mt.medium_created_by_server:
|
||||
raise CartError(error_messages['media_usage_not_implemented'])
|
||||
elif op.item.media_policy == Item.MEDIA_POLICY_REUSE:
|
||||
raise CartError(error_messages['media_usage_not_implemented'])
|
||||
|
||||
if self._sales_channel not in op.item.sales_channels or (op.variation and self._sales_channel not in op.variation.sales_channels):
|
||||
raise CartError(error_messages['unavailable'])
|
||||
|
||||
@@ -725,9 +738,18 @@ class CartManager:
|
||||
price_after_voucher = listed_price
|
||||
custom_price = None
|
||||
if item.free_price and i.get('price'):
|
||||
custom_price = Decimal(str(i.get('price')).replace(",", "."))
|
||||
custom_price = re.sub('[^0-9.,]', '', str(i.get('price')))
|
||||
if not custom_price:
|
||||
raise CartError(error_messages['price_not_a_number'])
|
||||
try:
|
||||
custom_price = forms.DecimalField(localize=True).to_python(custom_price)
|
||||
except:
|
||||
try:
|
||||
custom_price = Decimal(custom_price)
|
||||
except:
|
||||
raise CartError(error_messages['price_not_a_number'])
|
||||
if custom_price > 99_999_999_999:
|
||||
raise ValueError('price_too_high')
|
||||
raise CartError(error_messages['price_too_high'])
|
||||
|
||||
op = self.AddOperation(
|
||||
count=i['count'],
|
||||
@@ -840,9 +862,18 @@ class CartManager:
|
||||
listed_price = get_listed_price(item, variation, cp.subevent)
|
||||
custom_price = None
|
||||
if item.free_price and a.get('price'):
|
||||
custom_price = Decimal(str(a.get('price')).replace(",", "."))
|
||||
custom_price = re.sub('[^0-9.,]', '', a.get('price'))
|
||||
if not custom_price:
|
||||
raise CartError(error_messages['price_not_a_number'])
|
||||
try:
|
||||
custom_price = forms.DecimalField(localize=True).to_python(custom_price)
|
||||
except:
|
||||
try:
|
||||
custom_price = Decimal(custom_price)
|
||||
except:
|
||||
raise CartError(error_messages['price_not_a_number'])
|
||||
if custom_price > 99_999_999_999:
|
||||
raise ValueError('price_too_high')
|
||||
raise CartError(error_messages['price_too_high'])
|
||||
|
||||
# Fix positions with wrong price (TODO: happens out-of-cartmanager-transaction and therefore a little hacky)
|
||||
for ca in current_addons[cp][a['item'], a['variation']]:
|
||||
|
||||
@@ -693,7 +693,7 @@ def _save_answers(op, answers, given_answers):
|
||||
def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict, force=False,
|
||||
ignore_unpaid=False, nonce=None, datetime=None, questions_supported=True,
|
||||
user=None, auth=None, canceled_supported=False, type=Checkin.TYPE_ENTRY,
|
||||
raw_barcode=None, from_revoked_secret=False):
|
||||
raw_barcode=None, raw_source_type=None, from_revoked_secret=False):
|
||||
"""
|
||||
Create a checkin for this particular order position and check-in list. Fails with CheckInError if the check in is
|
||||
not valid at this time.
|
||||
@@ -714,40 +714,53 @@ def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict,
|
||||
# !!!!!!!!!
|
||||
|
||||
dt = datetime or now()
|
||||
force_used = False
|
||||
|
||||
if op.canceled or op.order.status not in (Order.STATUS_PAID, Order.STATUS_PENDING):
|
||||
raise CheckInError(
|
||||
_('This order position has been canceled.'),
|
||||
'canceled' if canceled_supported else 'unpaid'
|
||||
)
|
||||
if force:
|
||||
force_used = True
|
||||
else:
|
||||
raise CheckInError(
|
||||
_('This order position has been canceled.'),
|
||||
'canceled' if canceled_supported else 'unpaid'
|
||||
)
|
||||
|
||||
if op.blocked:
|
||||
raise CheckInError(
|
||||
_('This ticket has been blocked.'), # todo provide reason
|
||||
'blocked'
|
||||
)
|
||||
if force:
|
||||
force_used = True
|
||||
else:
|
||||
raise CheckInError(
|
||||
_('This ticket has been blocked.'), # todo provide reason
|
||||
'blocked'
|
||||
)
|
||||
|
||||
if type != Checkin.TYPE_EXIT and op.valid_from and op.valid_from > now():
|
||||
raise CheckInError(
|
||||
_('This ticket is only valid after {datetime}.').format(
|
||||
datetime=date_format(op.valid_from, 'SHORT_DATETIME_FORMAT')
|
||||
),
|
||||
'invalid_time',
|
||||
_('This ticket is only valid after {datetime}.').format(
|
||||
datetime=date_format(op.valid_from, 'SHORT_DATETIME_FORMAT')
|
||||
),
|
||||
)
|
||||
if force:
|
||||
force_used = True
|
||||
else:
|
||||
raise CheckInError(
|
||||
_('This ticket is only valid after {datetime}.').format(
|
||||
datetime=date_format(op.valid_from, 'SHORT_DATETIME_FORMAT')
|
||||
),
|
||||
'invalid_time',
|
||||
_('This ticket is only valid after {datetime}.').format(
|
||||
datetime=date_format(op.valid_from, 'SHORT_DATETIME_FORMAT')
|
||||
),
|
||||
)
|
||||
|
||||
if type != Checkin.TYPE_EXIT and op.valid_until and op.valid_until < now():
|
||||
raise CheckInError(
|
||||
_('This ticket was only valid before {datetime}.').format(
|
||||
datetime=date_format(op.valid_until, 'SHORT_DATETIME_FORMAT')
|
||||
),
|
||||
'invalid_time',
|
||||
_('This ticket was only valid before {datetime}.').format(
|
||||
datetime=date_format(op.valid_until, 'SHORT_DATETIME_FORMAT')
|
||||
),
|
||||
)
|
||||
if force:
|
||||
force_used = True
|
||||
else:
|
||||
raise CheckInError(
|
||||
_('This ticket was only valid before {datetime}.').format(
|
||||
datetime=date_format(op.valid_until, 'SHORT_DATETIME_FORMAT')
|
||||
),
|
||||
'invalid_time',
|
||||
_('This ticket was only valid before {datetime}.').format(
|
||||
datetime=date_format(op.valid_until, 'SHORT_DATETIME_FORMAT')
|
||||
),
|
||||
)
|
||||
|
||||
# Do this outside of transaction so it is saved even if the checkin fails for some other reason
|
||||
checkin_questions = list(
|
||||
@@ -770,40 +783,57 @@ def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict,
|
||||
op = opqs.get(pk=op.pk)
|
||||
|
||||
if not clist.all_products and op.item_id not in [i.pk for i in clist.limit_products.all()]:
|
||||
raise CheckInError(
|
||||
_('This order position has an invalid product for this check-in list.'),
|
||||
'product'
|
||||
)
|
||||
elif clist.subevent_id and op.subevent_id != clist.subevent_id:
|
||||
raise CheckInError(
|
||||
_('This order position has an invalid date for this check-in list.'),
|
||||
'product'
|
||||
)
|
||||
elif op.order.status != Order.STATUS_PAID and not force and op.order.require_approval:
|
||||
raise CheckInError(
|
||||
_('This order is not yet approved.'),
|
||||
'unpaid'
|
||||
)
|
||||
elif op.order.status != Order.STATUS_PAID and not force and not op.order.valid_if_pending and not (
|
||||
if force:
|
||||
force_used = True
|
||||
else:
|
||||
raise CheckInError(
|
||||
_('This order position has an invalid product for this check-in list.'),
|
||||
'product'
|
||||
)
|
||||
|
||||
if clist.subevent_id and op.subevent_id != clist.subevent_id:
|
||||
if force:
|
||||
force_used = True
|
||||
else:
|
||||
raise CheckInError(
|
||||
_('This order position has an invalid date for this check-in list.'),
|
||||
'product'
|
||||
)
|
||||
|
||||
if op.order.status != Order.STATUS_PAID and op.order.require_approval:
|
||||
if force:
|
||||
force_used = True
|
||||
else:
|
||||
raise CheckInError(
|
||||
_('This order is not yet approved.'),
|
||||
'unpaid'
|
||||
)
|
||||
elif op.order.status != Order.STATUS_PAID and not op.order.valid_if_pending and not (
|
||||
ignore_unpaid and clist.include_pending and op.order.status == Order.STATUS_PENDING
|
||||
):
|
||||
raise CheckInError(
|
||||
_('This order is not marked as paid.'),
|
||||
'unpaid'
|
||||
)
|
||||
if force:
|
||||
force_used = True
|
||||
else:
|
||||
raise CheckInError(
|
||||
_('This order is not marked as paid.'),
|
||||
'unpaid'
|
||||
)
|
||||
|
||||
if type == Checkin.TYPE_ENTRY and clist.rules and not force:
|
||||
if type == Checkin.TYPE_ENTRY and clist.rules:
|
||||
rule_data = LazyRuleVars(op, clist, dt)
|
||||
logic = _get_logic_environment(op.subevent or clist.event)
|
||||
if not logic.apply(clist.rules, rule_data):
|
||||
reason = _logic_explain(clist.rules, op.subevent or clist.event, rule_data)
|
||||
raise CheckInError(
|
||||
_('Entry not permitted: {explanation}.').format(
|
||||
explanation=reason
|
||||
),
|
||||
'rules',
|
||||
reason=reason
|
||||
)
|
||||
if force:
|
||||
force_used = True
|
||||
else:
|
||||
reason = _logic_explain(clist.rules, op.subevent or clist.event, rule_data)
|
||||
raise CheckInError(
|
||||
_('Entry not permitted: {explanation}.').format(
|
||||
explanation=reason
|
||||
),
|
||||
'rules',
|
||||
reason=reason
|
||||
)
|
||||
|
||||
if require_answers and not force and questions_supported:
|
||||
raise RequiredQuestionsError(
|
||||
@@ -837,9 +867,10 @@ def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict,
|
||||
device=device,
|
||||
gate=device.gate if device else None,
|
||||
nonce=nonce,
|
||||
forced=force and (not entry_allowed or from_revoked_secret),
|
||||
forced=force and (not entry_allowed or from_revoked_secret or force_used),
|
||||
force_sent=force,
|
||||
raw_barcode=raw_barcode,
|
||||
raw_source_type=raw_source_type,
|
||||
)
|
||||
op.order.log_action('pretix.event.checkin', data={
|
||||
'position': op.id,
|
||||
|
||||
@@ -62,6 +62,7 @@ from pretix.api.models import OAuthApplication
|
||||
from pretix.base.channels import get_all_sales_channels
|
||||
from pretix.base.email import get_email_context
|
||||
from pretix.base.i18n import get_language_without_region, language
|
||||
from pretix.base.media import MEDIA_TYPES
|
||||
from pretix.base.models import (
|
||||
CartPosition, Device, Event, GiftCard, Item, ItemVariation, Membership,
|
||||
Order, OrderPayment, OrderPosition, Quota, Seat, SeatCategoryMapping, User,
|
||||
@@ -2911,3 +2912,32 @@ def signal_listener_issue_memberships(sender: Event, order: Order, **kwargs):
|
||||
for p in order.positions.all():
|
||||
if p.item.grant_membership_type_id:
|
||||
create_membership(order.customer, p)
|
||||
|
||||
|
||||
@receiver(order_placed, dispatch_uid="pretixbase_order_placed_media")
|
||||
@receiver(order_changed, dispatch_uid="pretixbase_order_changed_media")
|
||||
@transaction.atomic()
|
||||
def signal_listener_issue_media(sender: Event, order: Order, **kwargs):
|
||||
from pretix.base.models import ReusableMedium
|
||||
|
||||
for p in order.positions.all():
|
||||
if p.item.media_policy in (Item.MEDIA_POLICY_NEW, Item.MEDIA_POLICY_REUSE_OR_NEW):
|
||||
mt = MEDIA_TYPES[p.item.media_type]
|
||||
if mt.medium_created_by_server and not p.linked_media.exists():
|
||||
rm = ReusableMedium.objects.create(
|
||||
organizer=sender.organizer,
|
||||
type=p.item.media_type,
|
||||
identifier=mt.generate_identifier(sender.organizer),
|
||||
active=True,
|
||||
customer=order.customer,
|
||||
linked_orderposition=p,
|
||||
)
|
||||
rm.log_action(
|
||||
'pretix.reusable_medium.created',
|
||||
data={
|
||||
'by_order': order.code,
|
||||
'linked_orderposition': p.pk,
|
||||
'active': True,
|
||||
'customer': order.customer_id,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
import re
|
||||
from decimal import Decimal
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
from django import forms
|
||||
from django.db.models import Q
|
||||
from django.utils.timezone import now
|
||||
|
||||
@@ -69,7 +71,16 @@ def get_price(item: Item, variation: ItemVariation = None,
|
||||
subtract_from_gross=bundled_sum)
|
||||
elif item.free_price and custom_price is not None and custom_price != "":
|
||||
if not isinstance(custom_price, Decimal):
|
||||
custom_price = Decimal(str(custom_price).replace(",", "."))
|
||||
custom_price = re.sub('[^0-9.,]', '', str(custom_price))
|
||||
if not custom_price:
|
||||
raise ValueError('price_not_a_number')
|
||||
try:
|
||||
custom_price = forms.DecimalField(localize=True).to_python(custom_price)
|
||||
except:
|
||||
try:
|
||||
custom_price = Decimal(custom_price)
|
||||
except:
|
||||
raise ValueError('price_not_a_number')
|
||||
if custom_price > 99_999_999_999:
|
||||
raise ValueError('price_too_high')
|
||||
|
||||
|
||||
@@ -169,6 +169,84 @@ DEFAULTS = {
|
||||
"was not logged in during the purchase.")
|
||||
)
|
||||
},
|
||||
'reusable_media_active': {
|
||||
'default': 'False',
|
||||
'type': bool,
|
||||
'form_class': forms.BooleanField,
|
||||
'serializer_class': serializers.BooleanField,
|
||||
'form_kwargs': dict(
|
||||
label=_("Activate re-usable media"),
|
||||
help_text=_("The re-usable media feature allows you to connect tickets and gift cards with physical media "
|
||||
"such as wristbands or chip cards that may be re-used for different tickets or gift cards "
|
||||
"later.")
|
||||
)
|
||||
},
|
||||
'reusable_media_type_barcode': {
|
||||
'default': 'False',
|
||||
'type': bool,
|
||||
'form_class': forms.BooleanField,
|
||||
'serializer_class': serializers.BooleanField,
|
||||
'form_kwargs': dict(
|
||||
label=_("Active"),
|
||||
)
|
||||
},
|
||||
'reusable_media_type_barcode_identifier_length': {
|
||||
'default': 24,
|
||||
'type': int,
|
||||
'form_class': forms.IntegerField,
|
||||
'serializer_class': serializers.IntegerField,
|
||||
'serializer_kwargs': dict(
|
||||
validators=[
|
||||
MinValueValidator(12),
|
||||
MaxValueValidator(64),
|
||||
]
|
||||
),
|
||||
'form_kwargs': dict(
|
||||
label=_('Length of barcodes'),
|
||||
validators=[
|
||||
MinValueValidator(12),
|
||||
MaxValueValidator(64),
|
||||
],
|
||||
required=True,
|
||||
widget=forms.NumberInput(
|
||||
attrs={
|
||||
'min': '12',
|
||||
'max': '64',
|
||||
},
|
||||
),
|
||||
)
|
||||
},
|
||||
'reusable_media_type_nfc_uid': {
|
||||
'default': 'False',
|
||||
'type': bool,
|
||||
'form_class': forms.BooleanField,
|
||||
'serializer_class': serializers.BooleanField,
|
||||
'form_kwargs': dict(
|
||||
label=_("Active"),
|
||||
)
|
||||
},
|
||||
'reusable_media_type_nfc_uid_autocreate_giftcard': {
|
||||
'default': 'False',
|
||||
'type': bool,
|
||||
'form_class': forms.BooleanField,
|
||||
'serializer_class': serializers.BooleanField,
|
||||
'form_kwargs': dict(
|
||||
label=_("Automatically create a new gift card if a previously unknown chip is seen"),
|
||||
)
|
||||
},
|
||||
'reusable_media_type_nfc_uid_autocreate_giftcard_currency': {
|
||||
'default': 'EUR',
|
||||
'type': str,
|
||||
'form_class': forms.ChoiceField,
|
||||
'serializer_class': serializers.ChoiceField,
|
||||
'serializer_kwargs': dict(
|
||||
choices=[(c.alpha_3, c.alpha_3 + " - " + c.name) for c in settings.CURRENCIES],
|
||||
),
|
||||
'form_kwargs': dict(
|
||||
choices=[(c.alpha_3, c.alpha_3 + " - " + c.name) for c in settings.CURRENCIES],
|
||||
label=_("Gift card currency"),
|
||||
)
|
||||
},
|
||||
'max_items_per_order': {
|
||||
'default': '10',
|
||||
'type': int,
|
||||
@@ -212,6 +290,8 @@ DEFAULTS = {
|
||||
'system_question_order': {
|
||||
'default': {},
|
||||
'type': dict,
|
||||
'serializer_class': serializers.DictField,
|
||||
'serializer_kwargs': lambda: dict(read_only=True, allow_empty=True),
|
||||
},
|
||||
'attendee_names_asked': {
|
||||
'default': 'True',
|
||||
@@ -3051,6 +3131,13 @@ def concatenation_for_salutation(d):
|
||||
return " ".join(filter(None, (salutation, title, given_name, family_name)))
|
||||
|
||||
|
||||
def get_name_parts_localized(name_parts, key):
|
||||
value = name_parts.get(key, "")
|
||||
if key == "salutation":
|
||||
return pgettext_lazy("person_name_salutation", value)
|
||||
return value
|
||||
|
||||
|
||||
PERSON_NAME_SCHEMES = OrderedDict([
|
||||
('given_family', {
|
||||
'fields': (
|
||||
@@ -3407,7 +3494,12 @@ def validate_organizer_settings(organizer, settings_dict):
|
||||
# organizer-settings either.
|
||||
#
|
||||
# N.B.: When actually fleshing out this stub, adding it to the OrganizerUpdateForm should be considered.
|
||||
pass
|
||||
"""
|
||||
if settings_dict.get('reusable_media_type_ntag_pretix1') and settings_dict.get('reusable_media_type_nfc_uid'):
|
||||
raise ValidationError({
|
||||
'reusable_media_type_nfc_uid': _('This needs to be disabled if other NFC-based types are active.')
|
||||
})
|
||||
"""
|
||||
|
||||
|
||||
def global_settings_object(holder):
|
||||
|
||||
@@ -39,7 +39,7 @@ from urllib.parse import urlencode, urlparse
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
|
||||
from django.core.validators import MaxValueValidator
|
||||
from django.db.models import Prefetch, Q, prefetch_related_objects
|
||||
from django.forms import (
|
||||
@@ -457,7 +457,49 @@ class EventUpdateForm(I18nModelForm):
|
||||
}
|
||||
|
||||
|
||||
class EventSettingsForm(SettingsForm):
|
||||
class EventSettingsValidationMixin:
|
||||
|
||||
def clean(self):
|
||||
data = super().clean()
|
||||
settings_dict = self.obj.settings.freeze()
|
||||
settings_dict.update(data)
|
||||
validate_event_settings(self.obj, settings_dict)
|
||||
return data
|
||||
|
||||
def add_error(self, field, error):
|
||||
# Copied from Django, but with improved handling for validation errors on fields that are not part of this form
|
||||
|
||||
if not isinstance(error, ValidationError):
|
||||
error = ValidationError(error)
|
||||
|
||||
if hasattr(error, 'error_dict'):
|
||||
if field is not None:
|
||||
raise TypeError(
|
||||
"The argument `field` must be `None` when the `error` "
|
||||
"argument contains errors for multiple fields."
|
||||
)
|
||||
else:
|
||||
error = error.error_dict
|
||||
else:
|
||||
error = {field or NON_FIELD_ERRORS: error.error_list}
|
||||
|
||||
for field, error_list in error.items():
|
||||
if field != NON_FIELD_ERRORS and field not in self.fields:
|
||||
field = NON_FIELD_ERRORS
|
||||
for e in error_list:
|
||||
e.message = _('A validation error has occurred on a setting that is not part of this form: {error}').format(error=e.message)
|
||||
|
||||
if field not in self.errors:
|
||||
if field == NON_FIELD_ERRORS:
|
||||
self._errors[field] = self.error_class(error_class='nonfield')
|
||||
else:
|
||||
self._errors[field] = self.error_class()
|
||||
self._errors[field].extend(error_list)
|
||||
if field in self.cleaned_data:
|
||||
del self.cleaned_data[field]
|
||||
|
||||
|
||||
class EventSettingsForm(EventSettingsValidationMixin, SettingsForm):
|
||||
timezone = forms.ChoiceField(
|
||||
choices=((a, a) for a in common_timezones),
|
||||
label=_("Event timezone"),
|
||||
@@ -573,13 +615,8 @@ class EventSettingsForm(SettingsForm):
|
||||
return data
|
||||
|
||||
def clean(self):
|
||||
self.cleaned_data = self._resolve_virtual_keys_input(self.cleaned_data)
|
||||
data = super().clean()
|
||||
settings_dict = self.event.settings.freeze()
|
||||
settings_dict.update(data)
|
||||
|
||||
data = self._resolve_virtual_keys_input(data)
|
||||
|
||||
validate_event_settings(self.event, data)
|
||||
return data
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -702,7 +739,7 @@ class CancelSettingsForm(SettingsForm):
|
||||
).format(self.obj.settings.giftcard_expiry_years)
|
||||
|
||||
|
||||
class PaymentSettingsForm(SettingsForm):
|
||||
class PaymentSettingsForm(EventSettingsValidationMixin, SettingsForm):
|
||||
auto_fields = [
|
||||
'payment_term_mode',
|
||||
'payment_term_days',
|
||||
@@ -734,13 +771,6 @@ class PaymentSettingsForm(SettingsForm):
|
||||
raise ValidationError(_("This field is required."))
|
||||
return value
|
||||
|
||||
def clean(self):
|
||||
data = super().clean()
|
||||
settings_dict = self.obj.settings.freeze()
|
||||
settings_dict.update(data)
|
||||
validate_event_settings(self.obj, data)
|
||||
return data
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['tax_rate_default'].queryset = self.obj.tax_rules.all()
|
||||
@@ -788,7 +818,7 @@ class ProviderForm(SettingsForm):
|
||||
return cleaned_data
|
||||
|
||||
|
||||
class InvoiceSettingsForm(SettingsForm):
|
||||
class InvoiceSettingsForm(EventSettingsValidationMixin, SettingsForm):
|
||||
|
||||
auto_fields = [
|
||||
'invoice_address_asked',
|
||||
@@ -863,13 +893,6 @@ class InvoiceSettingsForm(SettingsForm):
|
||||
)
|
||||
self.fields['invoice_numbers_counter_length'].validators.append(MaxValueValidator(15))
|
||||
|
||||
def clean(self):
|
||||
data = super().clean()
|
||||
settings_dict = self.obj.settings.freeze()
|
||||
settings_dict.update(data)
|
||||
validate_event_settings(self.obj, data)
|
||||
return data
|
||||
|
||||
|
||||
def contains_web_channel_validate(val):
|
||||
if "web" not in val:
|
||||
|
||||
@@ -569,6 +569,12 @@ class EventOrderExpertFilterForm(EventOrderFilterForm):
|
||||
label=_('Sales channel'),
|
||||
required=False,
|
||||
)
|
||||
checkin_attention = forms.NullBooleanField(
|
||||
required=False,
|
||||
widget=FilterNullBooleanSelect,
|
||||
label=_('Requires special attention'),
|
||||
help_text=_('Only matches orders with the attention checkbox set directly for the order, not based on the product.'),
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -689,6 +695,8 @@ class EventOrderExpertFilterForm(EventOrderFilterForm):
|
||||
qs = qs.filter(total=fdata.get('total'))
|
||||
if fdata.get('email_known_to_work') is not None:
|
||||
qs = qs.filter(email_known_to_work=fdata.get('email_known_to_work'))
|
||||
if fdata.get('checkin_attention') is not None:
|
||||
qs = qs.filter(checkin_attention=fdata.get('checkin_attention'))
|
||||
if fdata.get('locale'):
|
||||
qs = qs.filter(locale=fdata.get('locale'))
|
||||
if fdata.get('payment_sum_min') is not None:
|
||||
@@ -1419,6 +1427,62 @@ class CustomerFilterForm(FilterForm):
|
||||
return qs.distinct()
|
||||
|
||||
|
||||
class ReusableMediaFilterForm(FilterForm):
|
||||
orders = {
|
||||
'type': 'type',
|
||||
'identifier': 'identifier',
|
||||
}
|
||||
query = forms.CharField(
|
||||
label=_('Search query'),
|
||||
widget=forms.TextInput(attrs={
|
||||
'placeholder': _('Search query'),
|
||||
'autofocus': 'autofocus'
|
||||
}),
|
||||
required=False
|
||||
)
|
||||
status = forms.ChoiceField(
|
||||
label=_('Status'),
|
||||
required=False,
|
||||
choices=(
|
||||
('', _('All')),
|
||||
('active', _('active')),
|
||||
('disabled', _('disabled')),
|
||||
('expired', _('expired')),
|
||||
)
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.pop('request')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def filter_qs(self, qs):
|
||||
fdata = self.cleaned_data
|
||||
|
||||
if fdata.get('query'):
|
||||
query = fdata.get('query')
|
||||
qs = qs.filter(
|
||||
Q(identifier__icontains=query)
|
||||
| Q(customer__identifier__icontains=query)
|
||||
| Q(customer__external_identifier__istartswith=query)
|
||||
| Q(linked_orderposition__order__code__icontains=query)
|
||||
| Q(linked_giftcard__secret__icontains=query)
|
||||
)
|
||||
|
||||
if fdata.get('status') == 'active':
|
||||
qs = qs.filter(Q(expires__gt=now()) | Q(expires__isnull=False), active=True)
|
||||
elif fdata.get('status') == 'disabled':
|
||||
qs = qs.filter(active=False)
|
||||
elif fdata.get('status') == 'expired':
|
||||
qs = qs.filter(expires__lte=now())
|
||||
|
||||
if fdata.get('ordering'):
|
||||
qs = qs.order_by(self.get_order_by())
|
||||
else:
|
||||
qs = qs.order_by("identifier", "type", "organizer")
|
||||
|
||||
return qs.distinct()
|
||||
|
||||
|
||||
class TeamFilterForm(FilterForm):
|
||||
orders = {
|
||||
'name': 'name',
|
||||
|
||||
@@ -168,6 +168,7 @@ class QuestionForm(I18nModelForm):
|
||||
'valid_date_min',
|
||||
'valid_date_max',
|
||||
'valid_file_portrait',
|
||||
'valid_string_length_max',
|
||||
]
|
||||
widgets = {
|
||||
'valid_datetime_min': SplitDateTimePickerWidget(),
|
||||
@@ -401,6 +402,8 @@ class ItemCreateForm(I18nModelForm):
|
||||
'validity_dynamic_duration_months',
|
||||
'validity_dynamic_start_choice',
|
||||
'validity_dynamic_start_choice_day_limit',
|
||||
'media_type',
|
||||
'media_policy',
|
||||
)
|
||||
for f in fields:
|
||||
setattr(self.instance, f, getattr(src, f))
|
||||
@@ -592,6 +595,10 @@ class ItemUpdateForm(I18nModelForm):
|
||||
del self.fields['grant_membership_duration_days']
|
||||
del self.fields['grant_membership_duration_months']
|
||||
|
||||
if not self.event.settings.reusable_media_active:
|
||||
del self.fields['media_type']
|
||||
del self.fields['media_policy']
|
||||
|
||||
def clean(self):
|
||||
d = super().clean()
|
||||
if d['issue_giftcard']:
|
||||
@@ -635,6 +642,8 @@ class ItemUpdateForm(I18nModelForm):
|
||||
_("The start of validity must be before the end of validity.")
|
||||
)
|
||||
|
||||
Item.clean_media_settings(self.event, d.get('media_policy'), d.get('media_type'), d.get('issue_giftcard'))
|
||||
|
||||
return d
|
||||
|
||||
def clean_picture(self):
|
||||
@@ -693,6 +702,8 @@ class ItemUpdateForm(I18nModelForm):
|
||||
'validity_dynamic_duration_months',
|
||||
'validity_dynamic_start_choice',
|
||||
'validity_dynamic_start_choice_day_limit',
|
||||
'media_policy',
|
||||
'media_type',
|
||||
]
|
||||
field_classes = {
|
||||
'available_from': SplitDateTimeField,
|
||||
|
||||
@@ -41,10 +41,14 @@ from django.core.exceptions import ValidationError
|
||||
from django.db.models import Q
|
||||
from django.forms import inlineformset_factory
|
||||
from django.forms.utils import ErrorDict
|
||||
from django.urls import reverse
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.html import conditional_escape
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
from django_scopes.forms import SafeModelMultipleChoiceField
|
||||
from django_scopes.forms import (
|
||||
SafeModelChoiceField, SafeModelMultipleChoiceField,
|
||||
)
|
||||
from i18nfield.forms import (
|
||||
I18nFormField, I18nFormSetMixin, I18nTextarea, I18nTextInput,
|
||||
)
|
||||
@@ -62,15 +66,18 @@ from pretix.base.forms.questions import (
|
||||
from pretix.base.forms.widgets import SplitDateTimePickerWidget
|
||||
from pretix.base.models import (
|
||||
Customer, Device, EventMetaProperty, Gate, GiftCard, Membership,
|
||||
MembershipType, Organizer, Team,
|
||||
MembershipType, OrderPosition, Organizer, ReusableMedium, Team,
|
||||
)
|
||||
from pretix.base.models.customers import CustomerSSOClient, CustomerSSOProvider
|
||||
from pretix.base.models.organizer import OrganizerFooterLink
|
||||
from pretix.base.settings import PERSON_NAME_SCHEMES, PERSON_NAME_TITLE_GROUPS
|
||||
from pretix.base.settings import (
|
||||
PERSON_NAME_SCHEMES, PERSON_NAME_TITLE_GROUPS, validate_organizer_settings,
|
||||
)
|
||||
from pretix.control.forms import ExtFileField, SplitDateTimeField
|
||||
from pretix.control.forms.event import (
|
||||
SafeEventMultipleChoiceField, multimail_validate,
|
||||
)
|
||||
from pretix.control.forms.widgets import Select2
|
||||
from pretix.multidomain.models import KnownDomain
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
|
||||
@@ -208,6 +215,7 @@ class TeamForm(forms.ModelForm):
|
||||
fields = ['name', 'all_events', 'limit_events', 'can_create_events',
|
||||
'can_change_teams', 'can_change_organizer_settings',
|
||||
'can_manage_gift_cards', 'can_manage_customers',
|
||||
'can_manage_reusable_media',
|
||||
'can_change_event_settings', 'can_change_items',
|
||||
'can_view_orders', 'can_change_orders', 'can_checkin_orders',
|
||||
'can_view_vouchers', 'can_change_vouchers']
|
||||
@@ -389,6 +397,12 @@ class OrganizerSettingsForm(SettingsForm):
|
||||
'cookie_consent_dialog_text_secondary',
|
||||
'cookie_consent_dialog_button_yes',
|
||||
'cookie_consent_dialog_button_no',
|
||||
'reusable_media_active',
|
||||
'reusable_media_type_barcode',
|
||||
'reusable_media_type_barcode_identifier_length',
|
||||
'reusable_media_type_nfc_uid',
|
||||
'reusable_media_type_nfc_uid_autocreate_giftcard',
|
||||
'reusable_media_type_nfc_uid_autocreate_giftcard_currency',
|
||||
]
|
||||
|
||||
organizer_logo_image = ExtFileField(
|
||||
@@ -431,6 +445,26 @@ class OrganizerSettingsForm(SettingsForm):
|
||||
))
|
||||
for k, v in PERSON_NAME_TITLE_GROUPS.items()
|
||||
]
|
||||
self.fields['reusable_media_active'].label = mark_safe(
|
||||
conditional_escape(self.fields['reusable_media_active'].label) +
|
||||
' ' +
|
||||
'<span class="label label-info">{}</span>'.format(_('experimental'))
|
||||
)
|
||||
self.fields['reusable_media_active'].help_text = mark_safe(
|
||||
conditional_escape(self.fields['reusable_media_active'].help_text) +
|
||||
' ' +
|
||||
'<br/><span class="fa fa-flask"></span> ' +
|
||||
_('This feature is currently in an experimental stage. It only supports very limited use cases and might '
|
||||
'change at any point.')
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
data = super().clean()
|
||||
settings_dict = self.obj.settings.freeze()
|
||||
settings_dict.update(data)
|
||||
|
||||
validate_organizer_settings(self.obj, data)
|
||||
return data
|
||||
|
||||
|
||||
class MailSettingsForm(SettingsForm):
|
||||
@@ -626,6 +660,116 @@ class GiftCardUpdateForm(forms.ModelForm):
|
||||
}
|
||||
|
||||
|
||||
class SafeOrderPositionChoiceField(forms.ModelChoiceField):
|
||||
def __init__(self, queryset, **kwargs):
|
||||
queryset = queryset.model.all.none()
|
||||
super().__init__(queryset, **kwargs)
|
||||
|
||||
def label_from_instance(self, op):
|
||||
return f'{op.order.code}-{op.positionid} ({str(op.item) + ((" - " + str(op.variation)) if op.variation else "")})'
|
||||
|
||||
|
||||
class ReusableMediumUpdateForm(forms.ModelForm):
|
||||
error_messages = {
|
||||
'duplicate': _("An medium with this type and identifier is already registered."),
|
||||
}
|
||||
|
||||
class Meta:
|
||||
model = ReusableMedium
|
||||
fields = ['active', 'expires', 'customer', 'linked_giftcard', 'linked_orderposition', 'notes']
|
||||
field_classes = {
|
||||
'expires': SplitDateTimeField,
|
||||
'customer': SafeModelChoiceField,
|
||||
'linked_giftcard': SafeModelChoiceField,
|
||||
'linked_orderposition': SafeOrderPositionChoiceField,
|
||||
}
|
||||
widgets = {
|
||||
'expires': SplitDateTimePickerWidget,
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
organizer = self.instance.organizer
|
||||
|
||||
self.fields['linked_orderposition'].queryset = OrderPosition.all.filter(order__event__organizer=organizer).all()
|
||||
self.fields['linked_orderposition'].widget = Select2(
|
||||
attrs={
|
||||
'data-model-select2': 'generic',
|
||||
'data-select2-url': reverse('control:organizer.ticket_select2', kwargs={
|
||||
'organizer': organizer.slug,
|
||||
}),
|
||||
'data-placeholder': _('Ticket')
|
||||
}
|
||||
)
|
||||
self.fields['linked_orderposition'].widget.choices = self.fields['linked_orderposition'].choices
|
||||
self.fields['linked_orderposition'].required = False
|
||||
|
||||
self.fields['linked_giftcard'].queryset = organizer.issued_gift_cards.all()
|
||||
self.fields['linked_giftcard'].widget = Select2(
|
||||
attrs={
|
||||
'data-model-select2': 'generic',
|
||||
'data-select2-url': reverse('control:organizer.giftcards.select2', kwargs={
|
||||
'organizer': organizer.slug,
|
||||
}),
|
||||
'data-placeholder': _('Gift card')
|
||||
}
|
||||
)
|
||||
self.fields['linked_giftcard'].widget.choices = self.fields['linked_giftcard'].choices
|
||||
self.fields['linked_giftcard'].required = False
|
||||
|
||||
if organizer.settings.customer_accounts:
|
||||
self.fields['customer'].queryset = organizer.customers.all()
|
||||
self.fields['customer'].widget = Select2(
|
||||
attrs={
|
||||
'data-model-select2': 'generic',
|
||||
'data-select2-url': reverse('control:organizer.customers.select2', kwargs={
|
||||
'organizer': organizer.slug,
|
||||
}),
|
||||
'data-placeholder': _('Customer')
|
||||
}
|
||||
)
|
||||
self.fields['customer'].widget.choices = self.fields['customer'].choices
|
||||
self.fields['customer'].required = False
|
||||
else:
|
||||
del self.fields['customer']
|
||||
|
||||
def clean(self):
|
||||
identifier = self.cleaned_data.get('identifier')
|
||||
type = self.cleaned_data.get('type')
|
||||
|
||||
if identifier is not None and type is not None:
|
||||
try:
|
||||
self.instance.organizer.reusable_media.exclude(pk=self.instance.pk).get(
|
||||
identifier=identifier,
|
||||
type=type,
|
||||
)
|
||||
except ReusableMedium.DoesNotExist:
|
||||
pass
|
||||
else:
|
||||
raise forms.ValidationError(
|
||||
self.error_messages['duplicate'],
|
||||
code='duplicate',
|
||||
)
|
||||
|
||||
return self.cleaned_data
|
||||
|
||||
|
||||
class ReusableMediumCreateForm(ReusableMediumUpdateForm):
|
||||
|
||||
class Meta:
|
||||
model = ReusableMedium
|
||||
fields = ['active', 'type', 'identifier', 'expires', 'linked_orderposition', 'linked_giftcard', 'customer', 'notes']
|
||||
field_classes = {
|
||||
'expires': SplitDateTimeField,
|
||||
'customer': SafeModelChoiceField,
|
||||
'linked_giftcard': SafeModelChoiceField,
|
||||
'linked_orderposition': SafeOrderPositionChoiceField,
|
||||
}
|
||||
widgets = {
|
||||
'expires': SplitDateTimePickerWidget,
|
||||
}
|
||||
|
||||
|
||||
class CustomerUpdateForm(forms.ModelForm):
|
||||
error_messages = {
|
||||
'duplicate': _("An account with this email address is already registered."),
|
||||
|
||||
@@ -350,6 +350,8 @@ class VoucherBulkForm(VoucherForm):
|
||||
reader = csv.DictReader(StringIO(raw), dialect=dialect)
|
||||
except csv.Error as e:
|
||||
raise ValidationError(_('CSV parsing failed: {error}.').format(error=str(e)))
|
||||
if len(reader.fieldnames) == 1 and ',' in reader.fieldnames[0]:
|
||||
raise ValidationError(_('CSV input was not recognized to have multiple columns, maybe you have some invalid quoted field in your input.'))
|
||||
if 'email' not in reader.fieldnames:
|
||||
raise ValidationError(_('CSV input needs to contain a field with the header "{header}".').format(header="email"))
|
||||
unknown_fields = [f for f in reader.fieldnames if f not in ('email', 'name', 'tag', 'number')]
|
||||
|
||||
@@ -362,6 +362,10 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
'pretix.customer.anonymized': _('The account has been disabled and anonymized.'),
|
||||
'pretix.customer.password.resetrequested': _('A new password has been requested.'),
|
||||
'pretix.customer.password.set': _('A new password has been set.'),
|
||||
'pretix.reusable_medium.created': _('The reusable medium has been created.'),
|
||||
'pretix.reusable_medium.created.auto': _('The reusable medium has been created automatically.'),
|
||||
'pretix.reusable_medium.changed': _('The reusable medium has been changed.'),
|
||||
'pretix.reusable_medium.linked_orderposition.changed': _('The medium has been connected to a new ticket.'),
|
||||
'pretix.email.error': _('Sending of an email has failed.'),
|
||||
'pretix.event.comment': _('The event\'s internal comment has been updated.'),
|
||||
'pretix.event.canceled': _('The event has been canceled.'),
|
||||
@@ -470,6 +474,7 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
'pretix.voucher.redeemed': _('The voucher has been redeemed in order {order_code}.'),
|
||||
'pretix.event.item.added': _('The product has been created.'),
|
||||
'pretix.event.item.changed': _('The product has been changed.'),
|
||||
'pretix.event.item.reordered': _('The product has been reordered.'),
|
||||
'pretix.event.item.deleted': _('The product has been deleted.'),
|
||||
'pretix.event.item.variation.added': _('The variation "{value}" has been created.'),
|
||||
'pretix.event.item.variation.deleted': _('The variation "{value}" has been deleted.'),
|
||||
@@ -488,9 +493,11 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
'pretix.event.category.added': _('The category has been added.'),
|
||||
'pretix.event.category.deleted': _('The category has been deleted.'),
|
||||
'pretix.event.category.changed': _('The category has been changed.'),
|
||||
'pretix.event.category.reordered': _('The category has been reordered.'),
|
||||
'pretix.event.question.added': _('The question has been added.'),
|
||||
'pretix.event.question.deleted': _('The question has been deleted.'),
|
||||
'pretix.event.question.changed': _('The question has been changed.'),
|
||||
'pretix.event.question.reordered': _('The question has been reordered.'),
|
||||
'pretix.event.discount.added': _('The discount has been added.'),
|
||||
'pretix.event.discount.deleted': _('The discount has been deleted.'),
|
||||
'pretix.event.discount.changed': _('The discount has been changed.'),
|
||||
|
||||
@@ -578,6 +578,16 @@ def get_organizer_navigation(request):
|
||||
'children': children,
|
||||
})
|
||||
|
||||
if request.organizer.settings.reusable_media_active:
|
||||
nav.append({
|
||||
'label': _('Reusable media'),
|
||||
'url': reverse('control:organizer.reusable_media', kwargs={
|
||||
'organizer': request.organizer.slug
|
||||
}),
|
||||
'icon': 'key',
|
||||
'active': 'organizer.reusable_medi' in url.url_name,
|
||||
})
|
||||
|
||||
if 'can_change_organizer_settings' in request.orgapermset:
|
||||
nav.append({
|
||||
'label': _('Devices'),
|
||||
|
||||
@@ -46,4 +46,5 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</form>
|
||||
<!-- pretix-login-marker -->{# marker required for ajax calls to detect that user session is over #}
|
||||
{% endblock %}
|
||||
|
||||
@@ -16,6 +16,42 @@
|
||||
{% endif %}
|
||||
</small>
|
||||
</h1>
|
||||
<div class="helper-space-below">
|
||||
{% trans "Shop URL:" %}
|
||||
<span id="shop_url" class="text-muted">{% abseventurl request.event "presale:event.index" %}</span>
|
||||
<button type="button" class="btn btn-default btn-xs btn-clipboard js-only" data-clipboard-target="#shop_url">
|
||||
<i class="fa fa-clipboard" aria-hidden="true"></i>
|
||||
<span class="sr-only">{% trans "Copy to clipboard" %}</span>
|
||||
</button>
|
||||
<div class="btn-group helper-display-inline-block">
|
||||
<button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown" title="{% trans "Create QR code" %}" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fa fa-qrcode" aria-hidden="true"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-right">
|
||||
<li>
|
||||
<a href="{% url "control:event.qrcode" event=request.event.slug organizer=request.organizer.slug filetype="png" %}" target="_blank" download>
|
||||
{% blocktrans with filetype="PNG" %}Download QR code as {{ filetype }} image{% endblocktrans %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url "control:event.qrcode" event=request.event.slug organizer=request.organizer.slug filetype="svg" %}" target="_blank" download>
|
||||
{% blocktrans with filetype="SVG" %}Download QR code as {{ filetype }} image{% endblocktrans %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url "control:event.qrcode" event=request.event.slug organizer=request.organizer.slug filetype="jpeg" %}" target="_blank" download>
|
||||
{% blocktrans with filetype="JPG" %}Download QR code as {{ filetype }} image{% endblocktrans %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url "control:event.qrcode" event=request.event.slug organizer=request.organizer.slug filetype="gif" %}" target="_blank" download>
|
||||
{% blocktrans with filetype="GIF" %}Download QR code as {{ filetype }} image{% endblocktrans %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
{% if has_overpaid_orders %}
|
||||
<div class="alert alert-warning">
|
||||
{% blocktrans trimmed %}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
{% bootstrap_form_errors sform %}
|
||||
<div class="tabbed-form">
|
||||
<fieldset>
|
||||
<legend>{% trans "Basics" %}</legend>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
{% load formset_tags %}
|
||||
{% block inside %}
|
||||
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
||||
{% bootstrap_form_errors form layout="control" %}
|
||||
{% csrf_token %}
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-lg-10">
|
||||
@@ -178,6 +179,12 @@
|
||||
<fieldset>
|
||||
<legend>{% trans "Tickets & Badges" %}</legend>
|
||||
{% bootstrap_field form.generate_tickets layout="control" %}
|
||||
{% if form.media_policy %}
|
||||
{% bootstrap_field form.media_policy layout="control" %}
|
||||
{% endif %}
|
||||
{% if form.media_type %}
|
||||
{% bootstrap_field form.media_type layout="control" %}
|
||||
{% endif %}
|
||||
{% for f in plugin_forms %}
|
||||
{% if f.is_layouts %}
|
||||
{% bootstrap_form f layout="control" %}
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
{% bootstrap_field form.valid_datetime_min layout="control" %}
|
||||
{% bootstrap_field form.valid_datetime_max layout="control" %}
|
||||
</div>
|
||||
<div id="valid-string">
|
||||
{% bootstrap_field form.valid_string_length_max layout="control" %}
|
||||
</div>
|
||||
<div id="valid-file">
|
||||
{% bootstrap_field form.valid_file_portrait layout="control" %}
|
||||
</div>
|
||||
|
||||
@@ -462,6 +462,14 @@
|
||||
</dd>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% for m in line.linked_media.all %}
|
||||
<div class="cart-icon-details">
|
||||
<dd>
|
||||
<span class="fa fa-key fa-fw" aria-hidden="true"></span>
|
||||
<a href="{% url "control:organizer.reusable_medium" organizer=request.organizer.slug pk=m.pk %}">{{ m.identifier }}</a> <span class="text-muted">({{ m.get_type_display }})</span>
|
||||
</dd>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if not line.canceled %}
|
||||
<div class="position-buttons">
|
||||
{% if line.generate_ticket %}
|
||||
|
||||
@@ -200,6 +200,70 @@
|
||||
{% bootstrap_field sform.cookie_consent_dialog_button_yes layout="control" %}
|
||||
{% bootstrap_field sform.cookie_consent_dialog_button_no layout="control" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Reusable media" %}</legend>
|
||||
{% bootstrap_field sform.reusable_media_active layout="control" %}
|
||||
<div data-display-dependency="#{{ sform.reusable_media_active.id_for_label }}">
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">{% trans "Barcode media" %}</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="help-block">
|
||||
{% blocktrans trimmed %}
|
||||
A "barcode medium" can be any printed or digital representation of a barcode.
|
||||
The medium will initially be created through the sale of a product that has a
|
||||
media policy requiring such a medium as well as a ticket or badge layout that
|
||||
includes the "Reusable Medium ID" as a QR code. Later, the same barcode may
|
||||
be re-used during the sale of a different product.
|
||||
{% endblocktrans %}
|
||||
{% blocktrans trimmed %}
|
||||
Barcode media can currently only be connected to tickets.
|
||||
{% endblocktrans %}
|
||||
{% blocktrans trimmed %}
|
||||
This subsequent reuse of the barcode is currently only supported during POS sales.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
{% bootstrap_field sform.reusable_media_type_barcode layout="control" %}
|
||||
<div data-display-dependency="#{{ sform.reusable_media_type_barcode.id_for_label }}">
|
||||
{% bootstrap_field sform.reusable_media_type_barcode_identifier_length layout="control" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">{% trans "NFC UID-based" %}</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="help-block">
|
||||
{% blocktrans trimmed %}
|
||||
This medium type can work with almost any type of NFC chip. With this
|
||||
option, only the UID of the NFC chip is used for identification.
|
||||
{% endblocktrans %}
|
||||
{% blocktrans trimmed %}
|
||||
NFC media can currently only be connected to gift cards.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<p class="help-block">
|
||||
<span class="fa fa-warning text-warning"></span>
|
||||
{% blocktrans trimmed %}
|
||||
This method does not provide a high level of protection against abuse since it
|
||||
is possible for malicious users to clone someone's chip with the same UID.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
{% bootstrap_field sform.reusable_media_type_nfc_uid layout="control" %}
|
||||
<div data-display-dependency="#{{ sform.reusable_media_type_nfc_uid.id_for_label }}">
|
||||
{% bootstrap_field sform.reusable_media_type_nfc_uid_autocreate_giftcard layout="control" %}
|
||||
<div data-display-dependency="#{{ sform.reusable_media_type_nfc_uid_autocreate_giftcard.id_for_label }}">
|
||||
{% bootstrap_field sform.reusable_media_type_nfc_uid_autocreate_giftcard_currency layout="control" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Invoices" %}</legend>
|
||||
{% bootstrap_field sform.invoice_regenerate_allowed layout="control" %}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
{% extends "pretixcontrol/organizers/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load urlreplace %}
|
||||
{% load bootstrap3 %}
|
||||
{% load money %}
|
||||
{% block title %}{% trans "Reusable media" %}{% endblock %}
|
||||
{% block inner %}
|
||||
<h1>
|
||||
{% trans "Reusable media" %}
|
||||
</h1>
|
||||
{% if media|length == 0 and not filter_form.filtered %}
|
||||
<div class="empty-collection">
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
No media have been created yet.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<a href="{% url "control:organizer.reusable_medium.create" organizer=request.organizer.slug %}"
|
||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new medium" %}</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{% trans "Filter" %}</h3>
|
||||
</div>
|
||||
<form class="panel-body filter-form" action="" method="get">
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-sm-6 col-xs-12">
|
||||
{% bootstrap_field filter_form.query layout='inline' %}
|
||||
</div>
|
||||
<div class="col-md-6 col-sm-6 col-xs-12">
|
||||
{% bootstrap_field filter_form.status layout='inline' %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<button class="btn btn-primary btn-lg" type="submit">
|
||||
<span class="fa fa-filter"></span>
|
||||
{% trans "Filter" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<p>
|
||||
<a href="{% url "control:organizer.reusable_medium.create" organizer=request.organizer.slug %}"
|
||||
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new medium" %}</a>
|
||||
</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Identifier" context "reusable_media" %}
|
||||
<a href="?{% url_replace request 'ordering' '-identifier' %}"><i
|
||||
class="fa fa-caret-down"></i></a>
|
||||
<a href="?{% url_replace request 'ordering' 'identifier' %}"><i class="fa fa-caret-up"></i></a>
|
||||
</th>
|
||||
<th>{% trans "Media type" context "reusable_media" %}
|
||||
<a href="?{% url_replace request 'ordering' '-email' %}"><i class="fa fa-caret-down"></i></a>
|
||||
<a href="?{% url_replace request 'ordering' 'email' %}"><i class="fa fa-caret-up"></i></a></th>
|
||||
<th>{% trans "Connections" context "reusable_media" %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for m in media %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{% url "control:organizer.reusable_medium" organizer=request.organizer.slug pk=m.pk %}">
|
||||
{% if not m.active %}<strike>{% endif %}
|
||||
<strong>{{ m.identifier }}</strong>
|
||||
{% if not m.active %}</strike>{% endif %}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ m.get_type_display }}
|
||||
</td>
|
||||
<td>
|
||||
{% if m.customer %}
|
||||
<span class="helper-display-block">
|
||||
<span class="fa fa-user fa-fw"></span>
|
||||
<a href="{% url "control:organizer.customer" organizer=request.organizer.slug customer=m.customer.identifier %}">
|
||||
{{ m.customer }}
|
||||
</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if m.linked_orderposition %}
|
||||
<span class="helper-display-block">
|
||||
<span class="fa fa-ticket fa-fw"></span>
|
||||
<a href="{% url "control:event.order" event=m.linked_orderposition.order.event.slug organizer=request.organizer.slug code=m.linked_orderposition.order.code %}">
|
||||
{{ m.linked_orderposition.order.code }}</a>-{{ m.linked_orderposition.positionid }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if m.linked_giftcard %}
|
||||
<span class="helper-display-block">
|
||||
<span class="fa fa-credit-card fa-fw"></span>
|
||||
<a href="{% url "control:organizer.giftcard" organizer=request.organizer.slug giftcard=m.linked_giftcard.id %}">
|
||||
{{ m.linked_giftcard.secret }}</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<a href="{% url "control:organizer.reusable_medium" organizer=request.organizer.slug pk=m.pk %}"
|
||||
class="btn btn-default btn-sm" data-toggle="tooltip" title="{% trans "Details" %}">
|
||||
<i class="fa fa-eye"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% include "pretixcontrol/pagination.html" %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,93 @@
|
||||
{% extends "pretixcontrol/organizers/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% load money %}
|
||||
{% block title %}
|
||||
{% blocktrans trimmed with id=medium.identifier context "reusable_media" %}
|
||||
Medium {{ id }}
|
||||
{% endblocktrans %}
|
||||
{% endblock %}
|
||||
{% block inner %}
|
||||
<h1>
|
||||
{% blocktrans trimmed with id=medium.identifier context "reusable_media" %}
|
||||
Medium {{ id }}
|
||||
{% endblocktrans %}
|
||||
</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-10 col-xs-12">
|
||||
<div class="panel panel-primary items">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
{% trans "Details" %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Media type" context "reusable_media" %}</dt>
|
||||
<dd>{{ medium.get_type_display }}</dd>
|
||||
<dt>{% trans "Identifier" context "reusable_media" %}</dt>
|
||||
<dd><code>{{ medium.identifier }}</code></dd>
|
||||
<dt>{% trans "Status" %}</dt>
|
||||
<dd>
|
||||
{% if not medium.active %}
|
||||
{% trans "disabled" %}
|
||||
{% elif medium.is_expired %}
|
||||
{% trans "expired" %}
|
||||
{% else %}
|
||||
{% trans "active" %}
|
||||
{% endif %}
|
||||
</dd>
|
||||
<dt>{% trans "Connections" context "reusable_media" %}</dt>
|
||||
<dd>
|
||||
{% if medium.customer %}
|
||||
<span class="helper-display-block">
|
||||
<span class="fa fa-user fa-fw"></span>
|
||||
<a href="{% url "control:organizer.customer" organizer=request.organizer.slug customer=medium.customer.identifier %}">
|
||||
{{ medium.customer }}
|
||||
</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if medium.linked_orderposition %}
|
||||
<span class="helper-display-block">
|
||||
<span class="fa fa-ticket fa-fw"></span>
|
||||
<a href="{% url "control:event.order" event=medium.linked_orderposition.order.event.slug organizer=request.organizer.slug code=medium.linked_orderposition.order.code %}">
|
||||
{{ medium.linked_orderposition.order.code }}</a>-{{ medium.linked_orderposition.positionid }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if medium.linked_giftcard %}
|
||||
<span class="helper-display-block">
|
||||
<span class="fa fa-credit-card fa-fw"></span>
|
||||
<a href="{% url "control:organizer.giftcard" organizer=request.organizer.slug giftcard=medium.linked_giftcard.id %}">
|
||||
{{ medium.linked_giftcard.secret }}</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% if medium.notes %}
|
||||
<dt>{% trans "Notes" %}</dt>
|
||||
<dd>{{ medium.notes }}</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
</form>
|
||||
<div class="text-right">
|
||||
<a href="{% url "control:organizer.reusable_medium.edit" organizer=request.organizer.slug pk=medium.pk %}"
|
||||
class="btn btn-default">
|
||||
<i class="fa fa-edit"></i> {% trans "Edit" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2 col-xs-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
{% trans "Medium history" context "reusable_media" %}
|
||||
</h3>
|
||||
</div>
|
||||
{% include "pretixcontrol/includes/logs.html" with obj=medium %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,32 @@
|
||||
{% extends "pretixcontrol/organizers/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block title %}
|
||||
{% if not medium.pk %}
|
||||
{% trans "New medium" context "reusable_media" %}
|
||||
{% else %}
|
||||
{% blocktrans trimmed with id=medium.identifier context "reusable_media" %}
|
||||
Medium {{ id }}
|
||||
{% endblocktrans %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block inner %}
|
||||
<h1>
|
||||
{% if not medium.pk %}
|
||||
{% trans "New medium" context "reusable_media" %}
|
||||
{% else %}
|
||||
{% blocktrans trimmed with id=medium.identifier context "reusable_media" %}
|
||||
Medium {{ id }}
|
||||
{% endblocktrans %}
|
||||
{% endif %}
|
||||
</h1>
|
||||
<form class="form-horizontal" action="" method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form layout="control" %}
|
||||
<div class="form-group submit-group">
|
||||
<button type="submit" class="btn btn-primary btn-save">
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -24,6 +24,7 @@
|
||||
{% bootstrap_field form.can_create_events layout="control" %}
|
||||
{% bootstrap_field form.can_manage_gift_cards layout="control" %}
|
||||
{% bootstrap_field form.can_manage_customers layout="control" %}
|
||||
{% bootstrap_field form.can_manage_reusable_media layout="control" %}
|
||||
{% bootstrap_field form.can_change_teams layout="control" %}
|
||||
{% bootstrap_field form.can_change_organizer_settings layout="control" %}
|
||||
</fieldset>
|
||||
|
||||
@@ -174,6 +174,14 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="panel-body" id="toolbox-body">
|
||||
{% if name %}
|
||||
<div class="row control-group pdf-info">
|
||||
<div class="col-sm-12">
|
||||
<label>{% trans "Layout name" %}</label><br>
|
||||
<input type="text" id="pdf-info-name" class="input-block-level form-control" name="name" value="{{ name }}">
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="row control-group pdf-info">
|
||||
<div class="col-sm-6">
|
||||
<label>{% trans "Width (mm)" %}</label><br>
|
||||
@@ -455,6 +463,7 @@
|
||||
{% trans "Preview" %}
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary btn-save" id="editor-save">
|
||||
<span class="fa fa-fw fa-save"></span>
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -164,7 +164,15 @@ urlpatterns = [
|
||||
organizer.MembershipDeleteView.as_view(), name='organizer.customer.membership.delete'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/customer/(?P<customer>[^/]+)/anonymize$',
|
||||
organizer.CustomerAnonymizeView.as_view(), name='organizer.customer.anonymize'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/reusable_media$', organizer.ReusableMediaListView.as_view(), name='organizer.reusable_media'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/reusable_media/add$',
|
||||
organizer.ReusableMediumCreateView.as_view(), name='organizer.reusable_medium.create'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/reusable_media/(?P<pk>[^/]+)/$',
|
||||
organizer.ReusableMediumDetailView.as_view(), name='organizer.reusable_medium'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/reusable_media/(?P<pk>[^/]+)/edit$',
|
||||
organizer.ReusableMediumUpdateView.as_view(), name='organizer.reusable_medium.edit'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/giftcards$', organizer.GiftCardListView.as_view(), name='organizer.giftcards'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/giftcards/select2$', typeahead.giftcard_select2, name='organizer.giftcards.select2'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/giftcard/add$', organizer.GiftCardCreateView.as_view(), name='organizer.giftcard.add'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/giftcard/(?P<giftcard>[^/]+)/$', organizer.GiftCardDetailView.as_view(), name='organizer.giftcard'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/giftcard/(?P<giftcard>[^/]+)/edit$', organizer.GiftCardUpdateView.as_view(),
|
||||
@@ -213,6 +221,7 @@ urlpatterns = [
|
||||
name='organizer.export.scheduled.run'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/export/(?P<pk>[^/]+)/delete$', organizer.DeleteScheduledExportView.as_view(),
|
||||
name='organizer.export.scheduled.delete'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/ticket_select2$', typeahead.ticket_select2, name='organizer.ticket_select2'),
|
||||
re_path(r'^nav/typeahead/$', typeahead.nav_context_list, name='nav.typeahead'),
|
||||
re_path(r'^events/$', main.EventList.as_view(), name='events'),
|
||||
re_path(r'^events/add$', main.EventWizard.as_view(), name='events.add'),
|
||||
@@ -222,6 +231,7 @@ urlpatterns = [
|
||||
re_path(r'^search/payments/$', search.PaymentSearch.as_view(), name='search.payments'),
|
||||
re_path(r'^event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/', include([
|
||||
re_path(r'^$', dashboards.event_index, name='event.index'),
|
||||
re_path(r'^qrcode.(?P<filetype>(png|jpeg|gif|svg))$', event.EventQRCode.as_view(), name='event.qrcode'),
|
||||
re_path(r'^widgets.json$', dashboards.event_index_widgets_lazy, name='event.index.widgets'),
|
||||
re_path(r'^logs/embed$', dashboards.event_index_log_lazy, name='event.index.logs'),
|
||||
re_path(r'^live/$', event.EventLive.as_view(), name='event.live'),
|
||||
|
||||
@@ -38,10 +38,13 @@ import operator
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
from decimal import Decimal
|
||||
from io import BytesIO
|
||||
from itertools import groupby
|
||||
from urllib.parse import urlsplit
|
||||
|
||||
import bleach
|
||||
import qrcode
|
||||
import qrcode.image.svg
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
@@ -86,7 +89,7 @@ from pretix.control.permissions import EventPermissionRequiredMixin
|
||||
from pretix.control.views.mailsetup import MailSettingsSetupView
|
||||
from pretix.control.views.user import RecentAuthenticationRequiredMixin
|
||||
from pretix.helpers.database import rolledback_transaction
|
||||
from pretix.multidomain.urlreverse import get_event_domain
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri, get_event_domain
|
||||
from pretix.plugins.stripe.payment import StripeSettingsHolder
|
||||
from pretix.presale.style import regenerate_css
|
||||
|
||||
@@ -1504,3 +1507,35 @@ class QuickSetupView(FormView):
|
||||
},
|
||||
] if self.request.method != "POST" else []
|
||||
)
|
||||
|
||||
|
||||
class EventQRCode(EventPermissionRequiredMixin, View):
|
||||
permission = 'can_change_event_settings'
|
||||
|
||||
def get(self, request, *args, filetype, **kwargs):
|
||||
url = build_absolute_uri(request.event, 'presale:event.index')
|
||||
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_M,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
qr.add_data(url)
|
||||
qr.make(fit=True)
|
||||
|
||||
if filetype == 'svg':
|
||||
factory = qrcode.image.svg.SvgPathImage
|
||||
img = qrcode.make('Some data here', image_factory=factory)
|
||||
r = HttpResponse(img.to_string(), content_type='image/svg+xml')
|
||||
r['Content-Disposition'] = f'inline; filename="qrcode-{request.event.slug}.{filetype}"'
|
||||
return r
|
||||
elif filetype in ('jpeg', 'png', 'gif'):
|
||||
img = qr.make_image(fill_color="black", back_color="white")
|
||||
|
||||
byte_io = BytesIO()
|
||||
img.save(byte_io, filetype.upper())
|
||||
byte_io.seek(0)
|
||||
r = HttpResponse(byte_io.read(), content_type='image/' + filetype)
|
||||
r['Content-Disposition'] = f'inline; filename="qrcode-{request.event.slug}.{filetype}"'
|
||||
return r
|
||||
|
||||
@@ -136,6 +136,11 @@ def item_move(request, item, up=True):
|
||||
if item.position != i:
|
||||
item.position = i
|
||||
item.save()
|
||||
item.log_action(
|
||||
'pretix.event.item.reordered', user=request.user, data={
|
||||
'position': i,
|
||||
}
|
||||
)
|
||||
messages.success(request, _('The order of items has been updated.'))
|
||||
|
||||
|
||||
@@ -185,6 +190,11 @@ def reorder_items(request, organizer, event):
|
||||
if pos != i.position: # Save unneccessary UPDATE queries
|
||||
i.position = pos
|
||||
i.save(update_fields=['position'])
|
||||
i.log_action(
|
||||
'pretix.event.item.reordered', user=request.user, data={
|
||||
'position': i,
|
||||
}
|
||||
)
|
||||
|
||||
return HttpResponse()
|
||||
|
||||
@@ -243,7 +253,7 @@ class CategoryUpdate(EventPermissionRequiredMixin, UpdateView):
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
if form.has_changed():
|
||||
self.object.log_action(
|
||||
'pretix.event.category.changed', user=self.request.user, data={
|
||||
'pretix.event.category.reordered', user=self.request.user, data={
|
||||
k: form.cleaned_data.get(k) for k in form.changed_data
|
||||
}
|
||||
)
|
||||
@@ -338,6 +348,11 @@ def category_move(request, category, up=True):
|
||||
if cat.position != i:
|
||||
cat.position = i
|
||||
cat.save()
|
||||
cat.log_action(
|
||||
'pretix.event.category.reordered', user=request.user, data={
|
||||
'position': i,
|
||||
}
|
||||
)
|
||||
messages.success(request, _('The order of categories has been updated.'))
|
||||
|
||||
|
||||
@@ -381,6 +396,11 @@ def reorder_categories(request, organizer, event):
|
||||
if pos != c.position: # Save unneccessary UPDATE queries
|
||||
c.position = pos
|
||||
c.save(update_fields=['position'])
|
||||
c.log_action(
|
||||
'pretix.event.category.reordered', user=request.user, data={
|
||||
'position': pos,
|
||||
}
|
||||
)
|
||||
|
||||
return HttpResponse()
|
||||
|
||||
@@ -510,6 +530,11 @@ def reorder_questions(request, organizer, event):
|
||||
if pos != q.position: # Save unneccessary UPDATE queries
|
||||
q.position = pos
|
||||
q.save(update_fields=['position'])
|
||||
q.log_action(
|
||||
'pretix.event.question.reordered', user=request.user, data={
|
||||
'position': pos,
|
||||
}
|
||||
)
|
||||
|
||||
system_question_order = {}
|
||||
for s in ('attendee_name_parts', 'attendee_email', 'company', 'street', 'zipcode', 'city', 'country'):
|
||||
@@ -518,6 +543,11 @@ def reorder_questions(request, organizer, event):
|
||||
else:
|
||||
system_question_order[s] = -1
|
||||
request.event.settings.system_question_order = system_question_order
|
||||
request.event.log_action(
|
||||
'pretix.event.settings', user=request.user, data={
|
||||
'system_question_order': system_question_order,
|
||||
}
|
||||
)
|
||||
|
||||
return HttpResponse()
|
||||
|
||||
@@ -731,7 +761,7 @@ class QuestionUpdate(EventPermissionRequiredMixin, QuestionMixin, UpdateView):
|
||||
|
||||
if form.has_changed():
|
||||
self.object.log_action(
|
||||
'pretix.event.question.changed', user=self.request.user, data={
|
||||
'pretix.event.question.reordered', user=self.request.user, data={
|
||||
k: form.cleaned_data.get(k) for k in form.changed_data
|
||||
}
|
||||
)
|
||||
|
||||
@@ -367,7 +367,7 @@ class OrderDetail(OrderView):
|
||||
'item', 'variation', 'addon_to', 'tax_rule', 'used_membership', 'used_membership__membership_type',
|
||||
'discount',
|
||||
).prefetch_related(
|
||||
'item__questions', 'issued_gift_cards',
|
||||
'item__questions', 'issued_gift_cards', 'linked_media',
|
||||
Prefetch('answers', queryset=QuestionAnswer.objects.prefetch_related('options').select_related('question')),
|
||||
Prefetch('all_checkins', queryset=Checkin.all.select_related('list').order_by('datetime')),
|
||||
).order_by('positionid')
|
||||
|
||||
@@ -73,7 +73,7 @@ from pretix.base.i18n import language
|
||||
from pretix.base.models import (
|
||||
CachedFile, Customer, Device, Gate, GiftCard, Invoice, LogEntry,
|
||||
Membership, MembershipType, Order, OrderPayment, OrderPosition, Organizer,
|
||||
ScheduledOrganizerExport, Team, TeamInvite, User,
|
||||
ReusableMedium, ScheduledOrganizerExport, Team, TeamInvite, User,
|
||||
)
|
||||
from pretix.base.models.customers import CustomerSSOClient, CustomerSSOProvider
|
||||
from pretix.base.models.event import Event, EventMetaProperty, EventMetaValue
|
||||
@@ -92,7 +92,7 @@ from pretix.base.views.tasks import AsyncAction
|
||||
from pretix.control.forms.exports import ScheduledOrganizerExportForm
|
||||
from pretix.control.forms.filter import (
|
||||
CustomerFilterForm, DeviceFilterForm, EventFilterForm, GiftCardFilterForm,
|
||||
OrganizerFilterForm, TeamFilterForm,
|
||||
OrganizerFilterForm, ReusableMediaFilterForm, TeamFilterForm,
|
||||
)
|
||||
from pretix.control.forms.orders import ExporterForm
|
||||
from pretix.control.forms.organizer import (
|
||||
@@ -100,8 +100,9 @@ from pretix.control.forms.organizer import (
|
||||
EventMetaPropertyForm, GateForm, GiftCardCreateForm, GiftCardUpdateForm,
|
||||
MailSettingsForm, MembershipTypeForm, MembershipUpdateForm,
|
||||
OrganizerDeleteForm, OrganizerFooterLinkFormset, OrganizerForm,
|
||||
OrganizerSettingsForm, OrganizerUpdateForm, SSOClientForm, SSOProviderForm,
|
||||
TeamForm, WebHookForm,
|
||||
OrganizerSettingsForm, OrganizerUpdateForm, ReusableMediumCreateForm,
|
||||
ReusableMediumUpdateForm, SSOClientForm, SSOProviderForm, TeamForm,
|
||||
WebHookForm,
|
||||
)
|
||||
from pretix.control.forms.rrule import RRuleForm
|
||||
from pretix.control.logdisplay import OVERVIEW_BANLIST
|
||||
@@ -533,7 +534,7 @@ class OrganizerCreate(CreateView):
|
||||
organizer=form.instance, name=_('Administrators'),
|
||||
all_events=True, can_create_events=True, can_change_teams=True, can_manage_gift_cards=True,
|
||||
can_change_organizer_settings=True, can_change_event_settings=True, can_change_items=True,
|
||||
can_manage_customers=True,
|
||||
can_manage_customers=True, can_manage_reusable_media=True,
|
||||
can_view_orders=True, can_change_orders=True, can_view_vouchers=True, can_change_vouchers=True
|
||||
)
|
||||
t.members.add(self.request.user)
|
||||
@@ -2738,3 +2739,101 @@ class CustomerAnonymizeView(OrganizerDetailViewMixin, OrganizerPermissionRequire
|
||||
'organizer': self.request.organizer.slug,
|
||||
'customer': self.object.identifier,
|
||||
})
|
||||
|
||||
|
||||
class ReusableMediaListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, PaginationMixin, ListView):
|
||||
model = ReusableMedium
|
||||
template_name = 'pretixcontrol/organizers/reusable_media.html'
|
||||
permission = 'can_manage_reusable_media'
|
||||
context_object_name = 'media'
|
||||
|
||||
def get_queryset(self):
|
||||
qs = self.request.organizer.reusable_media.select_related(
|
||||
'customer', 'linked_orderposition', 'linked_orderposition__order', 'linked_orderposition__order__event',
|
||||
'linked_giftcard'
|
||||
)
|
||||
if self.filter_form.is_valid():
|
||||
qs = self.filter_form.filter_qs(qs)
|
||||
return qs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['filter_form'] = self.filter_form
|
||||
return ctx
|
||||
|
||||
@cached_property
|
||||
def filter_form(self):
|
||||
return ReusableMediaFilterForm(data=self.request.GET, request=self.request)
|
||||
|
||||
|
||||
class ReusableMediumDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, TemplateView):
|
||||
template_name = 'pretixcontrol/organizers/reusable_medium.html'
|
||||
permission = 'can_manage_reusable_media'
|
||||
|
||||
@cached_property
|
||||
def medium(self):
|
||||
return get_object_or_404(
|
||||
self.request.organizer.reusable_media,
|
||||
pk=self.kwargs.get('pk')
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['medium'] = self.medium
|
||||
return ctx
|
||||
|
||||
|
||||
class ReusableMediumCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView):
|
||||
template_name = 'pretixcontrol/organizers/reusable_medium_edit.html'
|
||||
permission = 'can_manage_reusable_media'
|
||||
context_object_name = 'medium'
|
||||
form_class = ReusableMediumCreateForm
|
||||
|
||||
def get_form_kwargs(self):
|
||||
ctx = super().get_form_kwargs()
|
||||
c = ReusableMedium(organizer=self.request.organizer)
|
||||
ctx['instance'] = c
|
||||
return ctx
|
||||
|
||||
def form_valid(self, form):
|
||||
r = super().form_valid(form)
|
||||
form.instance.log_action('pretix.reusable_medium.created', user=self.request.user, data={
|
||||
k: getattr(form.instance, k)
|
||||
for k in form.changed_data
|
||||
})
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
return r
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('control:organizer.reusable_medium', kwargs={
|
||||
'organizer': self.request.organizer.slug,
|
||||
'pk': self.object.pk,
|
||||
})
|
||||
|
||||
|
||||
class ReusableMediumUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView):
|
||||
template_name = 'pretixcontrol/organizers/reusable_medium_edit.html'
|
||||
permission = 'can_manage_reusable_media'
|
||||
context_object_name = 'medium'
|
||||
form_class = ReusableMediumUpdateForm
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
return get_object_or_404(
|
||||
self.request.organizer.reusable_media,
|
||||
pk=self.kwargs.get('pk')
|
||||
)
|
||||
|
||||
def form_valid(self, form):
|
||||
if form.has_changed():
|
||||
self.object.log_action('pretix.reusable_medium.changed', user=self.request.user, data={
|
||||
k: getattr(self.object, k)
|
||||
for k in form.changed_data
|
||||
})
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('control:organizer.reusable_medium', kwargs={
|
||||
'organizer': self.request.organizer.slug,
|
||||
'pk': self.object.pk,
|
||||
})
|
||||
|
||||
@@ -48,8 +48,8 @@ from django.utils.translation import gettext as _, pgettext
|
||||
|
||||
from pretix.base.models import (
|
||||
EventMetaProperty, EventMetaValue, ItemMetaProperty, ItemMetaValue,
|
||||
ItemVariation, ItemVariationMetaValue, Order, Organizer, SubEventMetaValue,
|
||||
User, Voucher,
|
||||
ItemVariation, ItemVariationMetaValue, Order, OrderPosition, Organizer,
|
||||
SubEventMetaValue, User, Voucher,
|
||||
)
|
||||
from pretix.control.forms.event import EventWizardCopyForm
|
||||
from pretix.control.permissions import (
|
||||
@@ -172,6 +172,104 @@ def event_list(request):
|
||||
return JsonResponse(doc)
|
||||
|
||||
|
||||
@organizer_permission_required(("can_manage_gift_cards", "can_manage_reusable_media"))
|
||||
def giftcard_select2(request, **kwargs):
|
||||
query = request.GET.get('query', '')
|
||||
try:
|
||||
page = int(request.GET.get('page', '1'))
|
||||
except ValueError:
|
||||
page = 1
|
||||
|
||||
if request.user.has_organizer_permission(request.organizer, 'can_manage_gift_cards', request):
|
||||
qs = request.organizer.issued_gift_cards.filter(
|
||||
Q(secret__icontains=query)
|
||||
).order_by('secret')
|
||||
else:
|
||||
qs = request.organizer.issued_gift_cards.filter(
|
||||
Q(secret__iexact=query)
|
||||
).order_by('secret')
|
||||
|
||||
if not query:
|
||||
qs = qs.none()
|
||||
|
||||
total = qs.count()
|
||||
pagesize = 20
|
||||
offset = (page - 1) * pagesize
|
||||
doc = {
|
||||
'results': [
|
||||
{
|
||||
'id': e.pk,
|
||||
'text': str(e),
|
||||
}
|
||||
for e in qs[offset:offset + pagesize]
|
||||
],
|
||||
'pagination': {
|
||||
"more": total >= (offset + pagesize)
|
||||
}
|
||||
}
|
||||
return JsonResponse(doc)
|
||||
|
||||
|
||||
@organizer_permission_required(("can_manage_reusable_media"))
|
||||
def ticket_select2(request, **kwargs):
|
||||
query = request.GET.get('query', '')
|
||||
try:
|
||||
page = int(request.GET.get('page', '1'))
|
||||
except ValueError:
|
||||
page = 1
|
||||
|
||||
qs_orders = OrderPosition.all.select_related('order', 'order__event', 'item', 'variation').filter(
|
||||
order__event__organizer=request.organizer,
|
||||
).order_by()
|
||||
|
||||
exact_match = Q(secret__iexact=query)
|
||||
soft_match = Q(secret__icontains=query)
|
||||
|
||||
qsplit = query.split("-")
|
||||
|
||||
if len(qsplit) >= 3 and qsplit[2].isdigit():
|
||||
soft_match |= Q(order__event__slug__iexact=qsplit[0], order__code__iexact=qsplit[1], positionid=qsplit[2])
|
||||
elif len(qsplit) >= 2 and qsplit[1].isdigit():
|
||||
soft_match |= Q(order__code__istartswith=qsplit[0], positionid=qsplit[1])
|
||||
elif len(qsplit) >= 2:
|
||||
soft_match |= Q(order__event__slug__iexact=qsplit[0], order__code__istartswith=qsplit[1])
|
||||
else:
|
||||
soft_match |= Q(order__code__istartswith=qsplit[0])
|
||||
|
||||
if not request.user.has_active_staff_session(request.session.session_key):
|
||||
qs_orders = qs_orders.filter(
|
||||
exact_match | (
|
||||
soft_match & (
|
||||
Q(order__event__organizer_id__in=request.user.teams.filter(all_events=True, can_view_orders=True).values_list('organizer', flat=True))
|
||||
| Q(order__event_id__in=request.user.teams.filter(can_view_orders=True).values_list('limit_events__id', flat=True))
|
||||
)
|
||||
)
|
||||
)
|
||||
else:
|
||||
qs_orders = qs_orders.filter(exact_match | soft_match)
|
||||
|
||||
if not query:
|
||||
qs_orders = qs_orders.none()
|
||||
|
||||
total = qs_orders.count()
|
||||
pagesize = 20
|
||||
offset = (page - 1) * pagesize
|
||||
doc = {
|
||||
'results': [
|
||||
{
|
||||
'id': op.pk,
|
||||
'text': f'{op.order.code}-{op.positionid} ({str(op.item) + ((" - " + str(op.variation)) if op.variation else "")})',
|
||||
'event': str(op.order.event)
|
||||
}
|
||||
for op in qs_orders[offset:offset + pagesize]
|
||||
],
|
||||
'pagination': {
|
||||
"more": total >= (offset + pagesize)
|
||||
}
|
||||
}
|
||||
return JsonResponse(doc)
|
||||
|
||||
|
||||
@organizer_permission_required("can_manage_customers")
|
||||
def customer_select2(request, **kwargs):
|
||||
query = request.GET.get('query', '')
|
||||
|
||||
@@ -22,11 +22,10 @@
|
||||
import json
|
||||
import re
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils import translation
|
||||
from django.utils.formats import get_format
|
||||
|
||||
from pretix import settings
|
||||
|
||||
date_conversion_to_moment = {
|
||||
'%a': 'ddd',
|
||||
'%A': 'dddd',
|
||||
|
||||
+2493
-2049
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-08 15:04+0000\n"
|
||||
"POT-Creation-Date: 2023-04-05 09:17+0000\n"
|
||||
"PO-Revision-Date: 2021-09-15 11:22+0000\n"
|
||||
"Last-Translator: Mohamed Tawfiq <mtawfiq@wafyapp.com>\n"
|
||||
"Language-Team: Arabic <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -502,48 +502,48 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr "QR الدخول"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:385
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:386
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "لا يمكن تحميل ملف PDF الخلفية للأسباب التالية:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:654
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:656
|
||||
msgid "Group of objects"
|
||||
msgstr "مجموعة من العناصر"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:660
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
msgid "Text object"
|
||||
msgstr "عنصر نص"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
msgid "Barcode area"
|
||||
msgstr "منطقة باركود"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
msgid "Image area"
|
||||
msgstr "منطقة صورة"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
msgid "Powered by pretix"
|
||||
msgstr "مدعوم من pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:670
|
||||
msgid "Object"
|
||||
msgstr "عنصر"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:672
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:674
|
||||
msgid "Ticket design"
|
||||
msgstr "تصميم التذكرة"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:963
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:986
|
||||
msgid "Saving failed."
|
||||
msgstr "فشلت عملية الحفظ."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1031
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1070
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1105
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr "حصل خطأ أثناء رفع ملف PDF الخاص بك، يرجى المحاولة مرة أخرى."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1088
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr "هل تريد أن تغادر المحرر دون حفظ التعديلات؟"
|
||||
|
||||
@@ -551,54 +551,54 @@ msgstr "هل تريد أن تغادر المحرر دون حفظ التعديل
|
||||
msgid "An error has occurred."
|
||||
msgstr "حدث خطأ."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:54
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:52
|
||||
msgid "Generating messages …"
|
||||
msgstr "توليد الرسائل …"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:107
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:109
|
||||
msgid "Unknown error."
|
||||
msgstr "خطأ غير معروف."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:307
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:309
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "اللون يتمتع بتباين كبير وتسهل قراءته!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:311
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:313
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr "اللون يحظى بتباين معقول ويمكن أن يكون مناسب للقراءة!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:315
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:317
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr "تباين اللون سيئ للخلفية البيضاء، الرجاء اختيار لون غامق."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:464
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:486
|
||||
msgid "Search query"
|
||||
msgstr "البحث في الاستفسارات"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:482
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
msgid "All"
|
||||
msgstr "الكل"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:483
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:485
|
||||
msgid "None"
|
||||
msgstr "لا شيء"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:487
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:489
|
||||
msgid "Selected only"
|
||||
msgstr "المختارة فقط"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:890
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:892
|
||||
msgid "Use a different name internally"
|
||||
msgstr "قم باستخدم اسم مختلف داخليا"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:926
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:932
|
||||
msgid "Click to close"
|
||||
msgstr "اضغط لاغلاق الصفحة"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:998
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:1007
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "لم تقم بحفظ التعديلات!"
|
||||
|
||||
@@ -691,89 +691,114 @@ msgstr "التوقيت المحلي:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:17
|
||||
msgctxt "widget"
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
msgctxt "widget"
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#, fuzzy, javascript-format
|
||||
#| msgid "Selected only"
|
||||
msgctxt "widget"
|
||||
msgid "Select %s"
|
||||
msgstr "المختارة فقط"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#, fuzzy, javascript-format
|
||||
#| msgctxt "widget"
|
||||
#| msgid "See variations"
|
||||
msgctxt "widget"
|
||||
msgid "Select variant %s"
|
||||
msgstr "أنظر إلى الاختلافات"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "Sold out"
|
||||
msgstr "تم البيع بالكامل"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "Buy"
|
||||
msgstr "اشتري"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
msgctxt "widget"
|
||||
msgid "Register"
|
||||
msgstr "سجل"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
msgctxt "widget"
|
||||
msgid "Reserved"
|
||||
msgstr "محجوز"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
msgctxt "widget"
|
||||
msgid "FREE"
|
||||
msgstr "مجاني"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
msgctxt "widget"
|
||||
msgid "from %(currency)s %(price)s"
|
||||
msgstr "من %(currency) s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
msgctxt "widget"
|
||||
msgid "incl. %(rate)s% %(taxname)s"
|
||||
msgstr "يشمل %(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
msgctxt "widget"
|
||||
msgid "plus %(rate)s% %(taxname)s"
|
||||
msgstr "بالإضافة إلى %(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr "شامل الضريبة"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr "بالإضافة إلى الضرائب"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "currently available: %s"
|
||||
msgstr "متوفر حاليا: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
msgctxt "widget"
|
||||
msgid "Only available with a voucher"
|
||||
msgstr "متوفرة مع القسيمة فقط"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:33
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "minimum amount to order: %s"
|
||||
msgstr "الحد الأدنى للطلب: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
msgctxt "widget"
|
||||
msgid "Close ticket shop"
|
||||
msgstr "إغلاق متجر التذاكر"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
msgctxt "widget"
|
||||
msgid "The ticket shop could not be loaded."
|
||||
msgstr "لا يمكن تحميل متجر التذاكر."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"There are currently a lot of users in this ticket shop. Please open the shop "
|
||||
"in a new tab to continue."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "Close ticket shop"
|
||||
@@ -781,24 +806,24 @@ msgctxt "widget"
|
||||
msgid "Open ticket shop"
|
||||
msgstr "إغلاق متجر التذاكر"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
msgctxt "widget"
|
||||
msgid "The cart could not be created. Please try again later"
|
||||
msgstr "لا يمكن إنشاء سلة التسوق. الرجاء المحاولة مرة أخرى في وقت لاحق"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:40
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"We could not create your cart, since there are currently too many users in "
|
||||
"this ticket shop. Please click \"Continue\" to retry in a new tab."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Waiting list"
|
||||
msgstr "قائمة الإنتظار"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"You currently have an active cart for this event. If you select more "
|
||||
@@ -807,82 +832,82 @@ msgstr ""
|
||||
"لديك الآن سلة تسوق مفعلة لهذا الحدث. إذا قمت باختيار منتجات أخرى سيتم "
|
||||
"إضافتها إلى سلة التسوق الموجودة حالياً."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
msgctxt "widget"
|
||||
msgid "Resume checkout"
|
||||
msgstr "استئناف الدفع"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgctxt "widget"
|
||||
msgid "Redeem a voucher"
|
||||
msgstr "استبدال قسيمة"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgctxt "widget"
|
||||
msgid "Redeem"
|
||||
msgstr "استبدال"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgctxt "widget"
|
||||
msgid "Voucher code"
|
||||
msgstr "رمز القسيمة"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgctxt "widget"
|
||||
msgid "Close"
|
||||
msgstr "إغلاق"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgctxt "widget"
|
||||
msgid "Continue"
|
||||
msgstr "استمرار"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgctxt "widget"
|
||||
msgid "See variations"
|
||||
msgstr "أنظر إلى الاختلافات"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr "اختر فعالية أخرى"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different date"
|
||||
msgstr "اختر تاريخا آخر"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr "العودة"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr "الشهر القادم"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr "الشهر السابق"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgctxt "widget"
|
||||
msgid "Next week"
|
||||
msgstr "الأسبوع القادم"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgctxt "widget"
|
||||
msgid "Previous week"
|
||||
msgstr "الأسبوع السابق"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgctxt "widget"
|
||||
msgid "Open seat selection"
|
||||
msgstr "خيارات المقاعد"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"Some or all ticket categories are currently sold out. If you want, you can "
|
||||
@@ -890,86 +915,86 @@ msgid ""
|
||||
"again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
#, fuzzy
|
||||
#| msgid "Load more"
|
||||
msgctxt "widget"
|
||||
msgid "Load more"
|
||||
msgstr "تحميل المزيد"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "Mo"
|
||||
msgstr "الإثنين"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "Tu"
|
||||
msgstr "الثلاثاء"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "We"
|
||||
msgstr "الأربعاء"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "Th"
|
||||
msgstr "الخميس"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:67
|
||||
msgid "Fr"
|
||||
msgstr "الجمعة"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
msgid "Sa"
|
||||
msgstr "السبت"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
msgid "Su"
|
||||
msgstr "الأحد"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
msgid "January"
|
||||
msgstr "يناير"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
msgid "February"
|
||||
msgstr "فبراير"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:70
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
msgid "March"
|
||||
msgstr "مارس"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:71
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
msgid "April"
|
||||
msgstr "أبريل"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
msgid "May"
|
||||
msgstr "مايو"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
msgid "June"
|
||||
msgstr "يونيو"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
msgid "July"
|
||||
msgstr "يوليو"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
msgid "August"
|
||||
msgstr "أغسطس"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:80
|
||||
msgid "September"
|
||||
msgstr "سبتمبر"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:81
|
||||
msgid "October"
|
||||
msgstr "أكتوبر"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:82
|
||||
msgid "November"
|
||||
msgstr "نوفمبر"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:83
|
||||
msgid "December"
|
||||
msgstr "ديسمبر"
|
||||
|
||||
|
||||
+2504
-2069
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-08 15:04+0000\n"
|
||||
"POT-Creation-Date: 2023-04-05 09:17+0000\n"
|
||||
"PO-Revision-Date: 2020-12-19 07:00+0000\n"
|
||||
"Last-Translator: albert <albert.serra.monner@gmail.com>\n"
|
||||
"Language-Team: Catalan <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -481,48 +481,48 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:385
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:386
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:654
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:656
|
||||
msgid "Group of objects"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:660
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
msgid "Text object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
msgid "Barcode area"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
msgid "Image area"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
msgid "Powered by pretix"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:670
|
||||
msgid "Object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:672
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:674
|
||||
msgid "Ticket design"
|
||||
msgstr "Disseny del tiquet"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:963
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:986
|
||||
msgid "Saving failed."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1031
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1070
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1105
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1088
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
|
||||
@@ -530,54 +530,54 @@ msgstr ""
|
||||
msgid "An error has occurred."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:54
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:52
|
||||
msgid "Generating messages …"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:107
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:109
|
||||
msgid "Unknown error."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:307
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:309
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:311
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:313
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:315
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:317
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:464
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:486
|
||||
msgid "Search query"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:482
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:483
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:485
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:487
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:489
|
||||
msgid "Selected only"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:890
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:892
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:926
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:932
|
||||
msgid "Click to close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:998
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:1007
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
@@ -662,193 +662,215 @@ msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:17
|
||||
msgctxt "widget"
|
||||
msgid "Sold out"
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
msgctxt "widget"
|
||||
msgid "Buy"
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Register"
|
||||
msgid "Select %s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Reserved"
|
||||
msgid "Select variant %s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "FREE"
|
||||
msgid "Sold out"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "from %(currency)s %(price)s"
|
||||
msgid "Buy"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
msgctxt "widget"
|
||||
msgid "incl. %(rate)s% %(taxname)s"
|
||||
msgid "Register"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
msgctxt "widget"
|
||||
msgid "plus %(rate)s% %(taxname)s"
|
||||
msgid "Reserved"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgid "FREE"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgid "from %(currency)s %(price)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
msgctxt "widget"
|
||||
msgid "incl. %(rate)s% %(taxname)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
msgctxt "widget"
|
||||
msgid "plus %(rate)s% %(taxname)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "currently available: %s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
msgctxt "widget"
|
||||
msgid "Only available with a voucher"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:33
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "minimum amount to order: %s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
msgctxt "widget"
|
||||
msgid "Close ticket shop"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
msgctxt "widget"
|
||||
msgid "The ticket shop could not be loaded."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"There are currently a lot of users in this ticket shop. Please open the shop "
|
||||
"in a new tab to continue."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
msgctxt "widget"
|
||||
msgid "Open ticket shop"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
msgctxt "widget"
|
||||
msgid "The cart could not be created. Please try again later"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:40
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"We could not create your cart, since there are currently too many users in "
|
||||
"this ticket shop. Please click \"Continue\" to retry in a new tab."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Waiting list"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"You currently have an active cart for this event. If you select more "
|
||||
"products, they will be added to your existing cart."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
msgctxt "widget"
|
||||
msgid "Resume checkout"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgctxt "widget"
|
||||
msgid "Redeem a voucher"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgctxt "widget"
|
||||
msgid "Redeem"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgctxt "widget"
|
||||
msgid "Voucher code"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgctxt "widget"
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgctxt "widget"
|
||||
msgid "Continue"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgctxt "widget"
|
||||
msgid "See variations"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different date"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgctxt "widget"
|
||||
msgid "Next week"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgctxt "widget"
|
||||
msgid "Previous week"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgctxt "widget"
|
||||
msgid "Open seat selection"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"Some or all ticket categories are currently sold out. If you want, you can "
|
||||
@@ -856,83 +878,83 @@ msgid ""
|
||||
"again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgctxt "widget"
|
||||
msgid "Load more"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "Mo"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "Tu"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "We"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "Th"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:67
|
||||
msgid "Fr"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
msgid "Sa"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
msgid "Su"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
msgid "January"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
msgid "February"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:70
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
msgid "March"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:71
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
msgid "April"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
msgid "May"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
msgid "June"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
msgid "July"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
msgid "August"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:80
|
||||
msgid "September"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:81
|
||||
msgid "October"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:82
|
||||
msgid "November"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:83
|
||||
msgid "December"
|
||||
msgstr ""
|
||||
|
||||
+6344
-4907
File diff suppressed because it is too large
Load Diff
@@ -7,9 +7,9 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-08 15:04+0000\n"
|
||||
"PO-Revision-Date: 2023-01-13 08:00+0000\n"
|
||||
"Last-Translator: tree <jan.stransky@arnal.cz>\n"
|
||||
"POT-Creation-Date: 2023-04-05 09:17+0000\n"
|
||||
"PO-Revision-Date: 2023-03-19 06:00+0000\n"
|
||||
"Last-Translator: Michael <michael.happl@gmx.at>\n"
|
||||
"Language-Team: Czech <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
"cs/>\n"
|
||||
"Language: cs\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 4.15\n"
|
||||
"X-Generator: Weblate 4.16.4\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -31,105 +31,103 @@ msgstr "Komentář:"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:34
|
||||
msgid "PayPal"
|
||||
msgstr ""
|
||||
msgstr "PayPal"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:35
|
||||
msgid "Venmo"
|
||||
msgstr ""
|
||||
msgstr "Venmo"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:36
|
||||
msgid "Apple Pay"
|
||||
msgstr ""
|
||||
msgstr "Apple Pay"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:37
|
||||
msgid "Itaú"
|
||||
msgstr ""
|
||||
msgstr "Itaú"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:38
|
||||
msgid "PayPal Credit"
|
||||
msgstr ""
|
||||
msgstr "PayPal Credit"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:39
|
||||
msgid "Credit Card"
|
||||
msgstr ""
|
||||
msgstr "Kreditní karta"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:40
|
||||
msgid "PayPal Pay Later"
|
||||
msgstr ""
|
||||
msgstr "PayPal Pay Later"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:41
|
||||
msgid "iDEAL"
|
||||
msgstr ""
|
||||
msgstr "iDEAL"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:42
|
||||
msgid "SEPA Direct Debit"
|
||||
msgstr ""
|
||||
msgstr "Inkasní příkaz SEPA"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:43
|
||||
msgid "Bancontact"
|
||||
msgstr ""
|
||||
msgstr "Bancontact"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:44
|
||||
msgid "giropay"
|
||||
msgstr ""
|
||||
msgstr "giropay"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:45
|
||||
msgid "SOFORT"
|
||||
msgstr ""
|
||||
msgstr "SOFORT"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:46
|
||||
#, fuzzy
|
||||
#| msgid "Yes"
|
||||
msgid "eps"
|
||||
msgstr "Ano"
|
||||
msgstr "eps"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:47
|
||||
msgid "MyBank"
|
||||
msgstr ""
|
||||
msgstr "MyBank"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:48
|
||||
msgid "Przelewy24"
|
||||
msgstr ""
|
||||
msgstr "Przelewy24"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:49
|
||||
msgid "Verkkopankki"
|
||||
msgstr ""
|
||||
msgstr "Verkkopankki"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:50
|
||||
msgid "PayU"
|
||||
msgstr ""
|
||||
msgstr "PayU"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:51
|
||||
msgid "BLIK"
|
||||
msgstr ""
|
||||
msgstr "BLIK"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:52
|
||||
msgid "Trustly"
|
||||
msgstr ""
|
||||
msgstr "Trustly"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:53
|
||||
msgid "Zimpler"
|
||||
msgstr ""
|
||||
msgstr "Zimpler"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:54
|
||||
msgid "Maxima"
|
||||
msgstr ""
|
||||
msgstr "Maxima"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:55
|
||||
msgid "OXXO"
|
||||
msgstr ""
|
||||
msgstr "OXXO"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:56
|
||||
msgid "Boleto"
|
||||
msgstr ""
|
||||
msgstr "Boleto"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:57
|
||||
msgid "WeChat Pay"
|
||||
msgstr ""
|
||||
msgstr "WeChat Pay"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:58
|
||||
msgid "Mercado Pago"
|
||||
msgstr ""
|
||||
msgstr "Mercado Pago"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:164
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
|
||||
@@ -144,12 +142,12 @@ msgstr "Potvrzuji vaši platbu …"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:247
|
||||
msgid "Payment method unavailable"
|
||||
msgstr ""
|
||||
msgstr "Způsob platby není k dispozici"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Placed orders"
|
||||
msgstr "Vytvořené objednávky"
|
||||
msgstr "Zadané objednávky"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
@@ -287,16 +285,12 @@ msgid "Ticket code revoked/changed"
|
||||
msgstr "Kód vstupenky změněn"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:61
|
||||
#, fuzzy
|
||||
#| msgid "Ticket not paid"
|
||||
msgid "Ticket blocked"
|
||||
msgstr "Vstupenka není zaplacena"
|
||||
msgstr "Vstupenka zablokována"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:62
|
||||
#, fuzzy
|
||||
#| msgid "Ticket not paid"
|
||||
msgid "Ticket not valid at this time"
|
||||
msgstr "Vstupenka není zaplacena"
|
||||
msgstr "Vstupenka je v tuto chvíli neplatná"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:63
|
||||
msgid "Order canceled"
|
||||
@@ -429,7 +423,7 @@ msgstr "Současný čas"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:71
|
||||
msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
||||
msgstr ""
|
||||
msgstr "Aktuální den týdne (1 = pondělí, 7 = neděle)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:75
|
||||
msgid "Number of previous entries"
|
||||
@@ -445,11 +439,11 @@ msgstr "Počet dní bez úprav"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:87
|
||||
msgid "Minutes since last entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
msgstr "Minuty od předchozího vstupu (-1 pro první vstup)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:91
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
msgstr "Minuty od prvního vstupu (-1 pro první vstup)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:112
|
||||
msgid "All of the conditions below (AND)"
|
||||
@@ -493,54 +487,54 @@ msgstr "minuty"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:122
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
msgstr "Duplikát"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:71
|
||||
msgid "Check-in QR"
|
||||
msgstr "Check-in QR kód"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:385
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:386
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "Pozadí PDF nemohl být načten:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:654
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:656
|
||||
msgid "Group of objects"
|
||||
msgstr "Skupina objektů"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:660
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
msgid "Text object"
|
||||
msgstr "Textový objekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
msgid "Barcode area"
|
||||
msgstr "Oblast s QR kódem"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
msgid "Image area"
|
||||
msgstr "Oblast obrazu"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Poháněno společností pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:670
|
||||
msgid "Object"
|
||||
msgstr "Objekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:672
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:674
|
||||
msgid "Ticket design"
|
||||
msgstr "Design vstupenky"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:963
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:986
|
||||
msgid "Saving failed."
|
||||
msgstr "Uložení se nepodařilo."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1031
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1070
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1105
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr "Při nahrávání souboru PDF došlo k problému, zkuste to prosím znovu."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1088
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr "Opravdu chcete opustit editor bez uložení změn?"
|
||||
|
||||
@@ -548,24 +542,24 @@ msgstr "Opravdu chcete opustit editor bez uložení změn?"
|
||||
msgid "An error has occurred."
|
||||
msgstr "Vyskytla se chyba."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:54
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:52
|
||||
msgid "Generating messages …"
|
||||
msgstr "Vytváření zpráv…"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:107
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:109
|
||||
msgid "Unknown error."
|
||||
msgstr "Neznámá chyba."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:307
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:309
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "Tato barva má velmi dobrý kontrast a je velmi dobře čitelná!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:311
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:313
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Tato barva má slušný kontrast a pravděpodobně je dostatečně dobře čitelná!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:315
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:317
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -573,32 +567,32 @@ msgstr ""
|
||||
"Tato barva je pro text na bílém pozadí špatně kontrastní, zvolte prosím "
|
||||
"tmavší odstín."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:464
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:486
|
||||
msgid "Search query"
|
||||
msgstr "Hledaný výraz"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:482
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
msgid "All"
|
||||
msgstr "Všechny"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:483
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:485
|
||||
msgid "None"
|
||||
msgstr "Žádný"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:487
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:489
|
||||
msgid "Selected only"
|
||||
msgstr "Pouze vybrané"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:890
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:892
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Interně používat jiný název"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:926
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:932
|
||||
msgid "Click to close"
|
||||
msgstr "Kliknutím zavřete"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:998
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:1007
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Máte neuložené změny!"
|
||||
|
||||
@@ -684,82 +678,107 @@ msgstr "Místní čas:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:17
|
||||
msgctxt "widget"
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
msgctxt "widget"
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#, fuzzy, javascript-format
|
||||
#| msgid "Selected only"
|
||||
msgctxt "widget"
|
||||
msgid "Select %s"
|
||||
msgstr "Pouze vybrané"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#, fuzzy, javascript-format
|
||||
#| msgctxt "widget"
|
||||
#| msgid "See variations"
|
||||
msgctxt "widget"
|
||||
msgid "Select variant %s"
|
||||
msgstr "Zobrazit možnosti"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "Sold out"
|
||||
msgstr "Vyprodáno"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "Buy"
|
||||
msgstr "Koupit"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
msgctxt "widget"
|
||||
msgid "Register"
|
||||
msgstr "Zaregistrovat"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
msgctxt "widget"
|
||||
msgid "Reserved"
|
||||
msgstr "Rezervováno"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
msgctxt "widget"
|
||||
msgid "FREE"
|
||||
msgstr "ZDARMA"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
msgctxt "widget"
|
||||
msgid "from %(currency)s %(price)s"
|
||||
msgstr "od %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
msgctxt "widget"
|
||||
msgid "incl. %(rate)s% %(taxname)s"
|
||||
msgstr "včetně %(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
msgctxt "widget"
|
||||
msgid "plus %(rate)s% %(taxname)s"
|
||||
msgstr "plus %(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr "včetně daní"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr "plus daně"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "currently available: %s"
|
||||
msgstr "aktuálně k dispozici: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
msgctxt "widget"
|
||||
msgid "Only available with a voucher"
|
||||
msgstr "K dispozici pouze s poukazem"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:33
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "minimum amount to order: %s"
|
||||
msgstr "minimální množství pro objednávku: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
msgctxt "widget"
|
||||
msgid "Close ticket shop"
|
||||
msgstr "Zavřít obchod"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
msgctxt "widget"
|
||||
msgid "The ticket shop could not be loaded."
|
||||
msgstr "Obchod vstupenek nemohl být načten."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"There are currently a lot of users in this ticket shop. Please open the shop "
|
||||
@@ -768,17 +787,17 @@ msgstr ""
|
||||
"V současné době je v tomto obchodě s vstupenkami mnoho uživatelů. Otevřete "
|
||||
"prosím obchod v nové kartě."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
msgctxt "widget"
|
||||
msgid "Open ticket shop"
|
||||
msgstr "Obchod vstupenek otevřit"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
msgctxt "widget"
|
||||
msgid "The cart could not be created. Please try again later"
|
||||
msgstr "Nákupní košík se nepodařilo vytvořit. Zkuste to prosím znovu"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:40
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"We could not create your cart, since there are currently too many users in "
|
||||
@@ -788,12 +807,12 @@ msgstr ""
|
||||
"mnoho uživatelů. Klikněte prosím na \"Pokračovat\" a zkuste to znovu na nové "
|
||||
"kartě."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Waiting list"
|
||||
msgstr "Čekací listina"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"You currently have an active cart for this event. If you select more "
|
||||
@@ -802,167 +821,170 @@ msgstr ""
|
||||
"V současné době máte aktivní košík pro tuto událost. Pokud vyberete další "
|
||||
"produkty, budou přidány do vašeho košíku."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
msgctxt "widget"
|
||||
msgid "Resume checkout"
|
||||
msgstr "Obnovit checkout"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgctxt "widget"
|
||||
msgid "Redeem a voucher"
|
||||
msgstr "Uplatnit poukázku"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgctxt "widget"
|
||||
msgid "Redeem"
|
||||
msgstr "Uplatnit"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgctxt "widget"
|
||||
msgid "Voucher code"
|
||||
msgstr "Kód poukázky"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgctxt "widget"
|
||||
msgid "Close"
|
||||
msgstr "Zavřít"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgctxt "widget"
|
||||
msgid "Continue"
|
||||
msgstr "Pokračovat"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgctxt "widget"
|
||||
msgid "See variations"
|
||||
msgstr "Zobrazit možnosti"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr "Vybrat jinou událost"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different date"
|
||||
msgstr "Vybrat jiný datum"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr "Zpět"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr "Následující měsíc"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr "Předchozí měsíc"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgctxt "widget"
|
||||
msgid "Next week"
|
||||
msgstr "Příští týden"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgctxt "widget"
|
||||
msgid "Previous week"
|
||||
msgstr "Předchozí týden"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgctxt "widget"
|
||||
msgid "Open seat selection"
|
||||
msgstr "Otevřete výběr sedadla"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"Some or all ticket categories are currently sold out. If you want, you can "
|
||||
"add yourself to the waiting list. We will then notify if seats are available "
|
||||
"again."
|
||||
msgstr ""
|
||||
"Některé nebo všechny kategorie vstupenek jsou v současné době vyprodány. "
|
||||
"Pokud chcete, můžete se přidat na čekací listinu. Poté vás budeme "
|
||||
"informovat, pokud budou místa opět volná."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgctxt "widget"
|
||||
msgid "Load more"
|
||||
msgstr "Načíst více"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "Mo"
|
||||
msgstr "Po"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "Tu"
|
||||
msgstr "Út"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "We"
|
||||
msgstr "St"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "Th"
|
||||
msgstr "Čt"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:67
|
||||
msgid "Fr"
|
||||
msgstr "Pá"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
msgid "Sa"
|
||||
msgstr "So"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
msgid "Su"
|
||||
msgstr "Ne"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
msgid "January"
|
||||
msgstr "Leden"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
msgid "February"
|
||||
msgstr "Únor"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:70
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
msgid "March"
|
||||
msgstr "Březen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:71
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
msgid "April"
|
||||
msgstr "Duben"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
msgid "May"
|
||||
msgstr "Květen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
msgid "June"
|
||||
msgstr "červen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
msgid "July"
|
||||
msgstr "Červenec"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
msgid "August"
|
||||
msgstr "Srpen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:80
|
||||
msgid "September"
|
||||
msgstr "Září"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:81
|
||||
msgid "October"
|
||||
msgstr "Říjen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:82
|
||||
msgid "November"
|
||||
msgstr "Listopad"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:83
|
||||
msgid "December"
|
||||
msgstr "Prosinec"
|
||||
|
||||
|
||||
+2457
-2042
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-08 15:04+0000\n"
|
||||
"POT-Creation-Date: 2023-04-05 09:17+0000\n"
|
||||
"PO-Revision-Date: 2022-12-01 17:00+0000\n"
|
||||
"Last-Translator: Mie Frydensbjerg <mif@aarhus.dk>\n"
|
||||
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -513,50 +513,50 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr "Check-in QR"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:385
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:386
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "Baggrunds-pdf'en kunne ikke hentes af følgende grund:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:654
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:656
|
||||
msgid "Group of objects"
|
||||
msgstr "Gruppe af objekter"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:660
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
msgid "Text object"
|
||||
msgstr "Tekstobjekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
msgid "Barcode area"
|
||||
msgstr "QR-kode-område"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
#, fuzzy
|
||||
#| msgid "Barcode area"
|
||||
msgid "Image area"
|
||||
msgstr "QR-kode-område"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Drevet af pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:670
|
||||
msgid "Object"
|
||||
msgstr "Objekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:672
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:674
|
||||
msgid "Ticket design"
|
||||
msgstr "Billetdesign"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:963
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:986
|
||||
msgid "Saving failed."
|
||||
msgstr "Gem fejlede."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1031
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1070
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1105
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr "Fejl under upload af pdf. Prøv venligt igen."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1088
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
"Er du sikker på at du vil forlade editoren uden at gemme dine ændringer?"
|
||||
@@ -565,54 +565,54 @@ msgstr ""
|
||||
msgid "An error has occurred."
|
||||
msgstr "Der er sket en fejl."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:54
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:52
|
||||
msgid "Generating messages …"
|
||||
msgstr "Opretter beskeder …"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:107
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:109
|
||||
msgid "Unknown error."
|
||||
msgstr "Ukendt fejl."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:307
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:309
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:311
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:313
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:315
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:317
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:464
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:486
|
||||
msgid "Search query"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:482
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:483
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:485
|
||||
msgid "None"
|
||||
msgstr "Ingen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:487
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:489
|
||||
msgid "Selected only"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:890
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:892
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:926
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:932
|
||||
msgid "Click to close"
|
||||
msgstr "Klik for at lukke"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:998
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:1007
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Du har ændringer, der ikke er gemt!"
|
||||
|
||||
@@ -707,89 +707,113 @@ msgstr "Din lokaltid:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:17
|
||||
msgctxt "widget"
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
msgctxt "widget"
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Select %s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#, fuzzy, javascript-format
|
||||
#| msgctxt "widget"
|
||||
#| msgid "See variations"
|
||||
msgctxt "widget"
|
||||
msgid "Select variant %s"
|
||||
msgstr "Vis varianter"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "Sold out"
|
||||
msgstr "Udsolgt"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "Buy"
|
||||
msgstr "Læg i kurv"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
msgctxt "widget"
|
||||
msgid "Register"
|
||||
msgstr "Book nu"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
msgctxt "widget"
|
||||
msgid "Reserved"
|
||||
msgstr "Reserveret"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
msgctxt "widget"
|
||||
msgid "FREE"
|
||||
msgstr "GRATIS"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
msgctxt "widget"
|
||||
msgid "from %(currency)s %(price)s"
|
||||
msgstr "fra %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
msgctxt "widget"
|
||||
msgid "incl. %(rate)s% %(taxname)s"
|
||||
msgstr "inkl. %(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
msgctxt "widget"
|
||||
msgid "plus %(rate)s% %(taxname)s"
|
||||
msgstr "plus %(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr "inkl. moms"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr "plus moms"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "currently available: %s"
|
||||
msgstr "tilgængelig: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
msgctxt "widget"
|
||||
msgid "Only available with a voucher"
|
||||
msgstr "Kun tilgængelig med en rabatkode"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:33
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "minimum amount to order: %s"
|
||||
msgstr "minimumsantal: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
msgctxt "widget"
|
||||
msgid "Close ticket shop"
|
||||
msgstr "Luk billetbutik"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
msgctxt "widget"
|
||||
msgid "The ticket shop could not be loaded."
|
||||
msgstr "Billetbutikken kunne ikke hentes."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"There are currently a lot of users in this ticket shop. Please open the shop "
|
||||
"in a new tab to continue."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "Close ticket shop"
|
||||
@@ -797,24 +821,24 @@ msgctxt "widget"
|
||||
msgid "Open ticket shop"
|
||||
msgstr "Luk billetbutik"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
msgctxt "widget"
|
||||
msgid "The cart could not be created. Please try again later"
|
||||
msgstr "Kurven kunne ikke oprettes. Prøv igen senere"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:40
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"We could not create your cart, since there are currently too many users in "
|
||||
"this ticket shop. Please click \"Continue\" to retry in a new tab."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Waiting list"
|
||||
msgstr "Venteliste"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"You currently have an active cart for this event. If you select more "
|
||||
@@ -823,72 +847,72 @@ msgstr ""
|
||||
"Du har allerede en aktiv booking i gang for dette arrangement. Hvis du "
|
||||
"vælger flere produkter, så vil de blive tilføjet din eksisterende booking."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
msgctxt "widget"
|
||||
msgid "Resume checkout"
|
||||
msgstr "Fortsæt booking"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgctxt "widget"
|
||||
msgid "Redeem a voucher"
|
||||
msgstr "Indløs rabatkode"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgctxt "widget"
|
||||
msgid "Redeem"
|
||||
msgstr "Indløs"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgctxt "widget"
|
||||
msgid "Voucher code"
|
||||
msgstr "Rabatkode"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgctxt "widget"
|
||||
msgid "Close"
|
||||
msgstr "Luk"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgctxt "widget"
|
||||
msgid "Continue"
|
||||
msgstr "Fortsæt"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgctxt "widget"
|
||||
msgid "See variations"
|
||||
msgstr "Vis varianter"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr "Vælg et andet arrangement"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different date"
|
||||
msgstr "Vælg en anden dato"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr "Tilbage"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr "Næste måned"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr "Forrige måned"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgctxt "widget"
|
||||
msgid "Next week"
|
||||
msgstr "Næste uge"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "Previous month"
|
||||
@@ -896,12 +920,12 @@ msgctxt "widget"
|
||||
msgid "Previous week"
|
||||
msgstr "Forrige måned"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgctxt "widget"
|
||||
msgid "Open seat selection"
|
||||
msgstr "Åbn sædevalg"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"Some or all ticket categories are currently sold out. If you want, you can "
|
||||
@@ -909,84 +933,84 @@ msgid ""
|
||||
"again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgctxt "widget"
|
||||
msgid "Load more"
|
||||
msgstr "Hent flere"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "Mo"
|
||||
msgstr "Man"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "Tu"
|
||||
msgstr "Tirs"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "We"
|
||||
msgstr "Ons"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "Th"
|
||||
msgstr "Tors"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:67
|
||||
msgid "Fr"
|
||||
msgstr "Fre"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
msgid "Sa"
|
||||
msgstr "Lør"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
msgid "Su"
|
||||
msgstr "Søn"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
msgid "January"
|
||||
msgstr "Januar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
msgid "February"
|
||||
msgstr "Februar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:70
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
msgid "March"
|
||||
msgstr "Marts"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:71
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
msgid "April"
|
||||
msgstr "April"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
msgid "May"
|
||||
msgstr "Maj"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
msgid "June"
|
||||
msgstr "Juni"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
msgid "July"
|
||||
msgstr "Juli"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
msgid "August"
|
||||
msgstr "August"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:80
|
||||
msgid "September"
|
||||
msgstr "September"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:81
|
||||
msgid "October"
|
||||
msgstr "Oktober"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:82
|
||||
msgid "November"
|
||||
msgstr "November"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:83
|
||||
msgid "December"
|
||||
msgstr "December"
|
||||
|
||||
|
||||
+2511
-2052
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-08 15:04+0000\n"
|
||||
"POT-Creation-Date: 2023-04-05 09:17+0000\n"
|
||||
"PO-Revision-Date: 2023-02-09 13:56+0000\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: German <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -496,49 +496,49 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr "Check-in-QR-Code"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:385
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:386
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "Die Hintergrund-PDF-Datei konnte nicht geladen werden:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:654
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:656
|
||||
msgid "Group of objects"
|
||||
msgstr "Gruppe von Objekten"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:660
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
msgid "Text object"
|
||||
msgstr "Text-Objekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
msgid "Barcode area"
|
||||
msgstr "QR-Code-Bereich"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
msgid "Image area"
|
||||
msgstr "Bildbereich"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Event-Ticketshop von pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:670
|
||||
msgid "Object"
|
||||
msgstr "Objekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:672
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:674
|
||||
msgid "Ticket design"
|
||||
msgstr "Ticket-Design"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:963
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:986
|
||||
msgid "Saving failed."
|
||||
msgstr "Speichern fehlgeschlagen."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1031
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1070
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1105
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
"Es gab ein Problem beim Hochladen der PDF-Datei, bitte erneut versuchen."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1088
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
"Möchten Sie den Editor wirklich schließen ohne Ihre Änderungen zu speichern?"
|
||||
@@ -547,25 +547,25 @@ msgstr ""
|
||||
msgid "An error has occurred."
|
||||
msgstr "Ein Fehler ist aufgetreten."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:54
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:52
|
||||
msgid "Generating messages …"
|
||||
msgstr "Generiere Nachrichten…"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:107
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:109
|
||||
msgid "Unknown error."
|
||||
msgstr "Unbekannter Fehler."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:307
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:309
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "Diese Farbe hat einen sehr guten Kontrast und ist sehr gut zu lesen!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:311
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:313
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Diese Farbe hat einen ausreichenden Kontrast und ist wahrscheinlich gut zu "
|
||||
"lesen!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:315
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:317
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -573,32 +573,32 @@ msgstr ""
|
||||
"Diese Farbe hat einen schlechten Kontrast für Text auf einem weißen "
|
||||
"Hintergrund. Bitte wählen Sie eine dunklere Farbe."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:464
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:486
|
||||
msgid "Search query"
|
||||
msgstr "Suchbegriff"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:482
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:483
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:485
|
||||
msgid "None"
|
||||
msgstr "Keine"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:487
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:489
|
||||
msgid "Selected only"
|
||||
msgstr "Nur ausgewählte"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:890
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:892
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Intern einen anderen Namen verwenden"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:926
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:932
|
||||
msgid "Click to close"
|
||||
msgstr "Klicken zum Schließen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:998
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:1007
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Sie haben ungespeicherte Änderungen!"
|
||||
|
||||
@@ -682,82 +682,107 @@ msgstr "Deine lokale Zeit:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:17
|
||||
msgctxt "widget"
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
msgctxt "widget"
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#, fuzzy, javascript-format
|
||||
#| msgid "Selected only"
|
||||
msgctxt "widget"
|
||||
msgid "Select %s"
|
||||
msgstr "Nur ausgewählte"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#, fuzzy, javascript-format
|
||||
#| msgctxt "widget"
|
||||
#| msgid "See variations"
|
||||
msgctxt "widget"
|
||||
msgid "Select variant %s"
|
||||
msgstr "Varianten zeigen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "Sold out"
|
||||
msgstr "Ausverkauft"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "Buy"
|
||||
msgstr "In den Warenkorb"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
msgctxt "widget"
|
||||
msgid "Register"
|
||||
msgstr "Anmelden"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
msgctxt "widget"
|
||||
msgid "Reserved"
|
||||
msgstr "Reserviert"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
msgctxt "widget"
|
||||
msgid "FREE"
|
||||
msgstr "GRATIS"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
msgctxt "widget"
|
||||
msgid "from %(currency)s %(price)s"
|
||||
msgstr "ab %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
msgctxt "widget"
|
||||
msgid "incl. %(rate)s% %(taxname)s"
|
||||
msgstr "inkl. %(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
msgctxt "widget"
|
||||
msgid "plus %(rate)s% %(taxname)s"
|
||||
msgstr "zzgl. %(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr "inkl. Steuern"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr "zzgl. Steuern"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "currently available: %s"
|
||||
msgstr "aktuell verfügbar: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
msgctxt "widget"
|
||||
msgid "Only available with a voucher"
|
||||
msgstr "Nur mit Gutschein verfügbar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:33
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "minimum amount to order: %s"
|
||||
msgstr "minimale Bestellmenge: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
msgctxt "widget"
|
||||
msgid "Close ticket shop"
|
||||
msgstr "Ticket-Shop schließen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
msgctxt "widget"
|
||||
msgid "The ticket shop could not be loaded."
|
||||
msgstr "Der Ticket-Shop konnte nicht geladen werden."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"There are currently a lot of users in this ticket shop. Please open the shop "
|
||||
@@ -766,17 +791,17 @@ msgstr ""
|
||||
"Es sind derzeit sehr viele Benutzer in diesem Ticketshop. Bitte öffnen Sie "
|
||||
"diesen Ticketshop in einem neuen Tab um fortzufahren."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
msgctxt "widget"
|
||||
msgid "Open ticket shop"
|
||||
msgstr "Ticket-Shop öffnen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
msgctxt "widget"
|
||||
msgid "The cart could not be created. Please try again later"
|
||||
msgstr "Der Warenkorb konnte nicht erstellt werden. Bitte erneut versuchen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:40
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"We could not create your cart, since there are currently too many users in "
|
||||
@@ -786,12 +811,12 @@ msgstr ""
|
||||
"diesem Ticketshop sind. Bitte klicken Sie \"Weiter\" um es in einem neuen "
|
||||
"Tab erneut zu versuchen."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Waiting list"
|
||||
msgstr "Warteliste"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"You currently have an active cart for this event. If you select more "
|
||||
@@ -800,82 +825,82 @@ msgstr ""
|
||||
"Sie haben einen aktiven Warenkorb für diese Veranstaltung. Wenn Sie mehr "
|
||||
"Produkte auswählen, werden diese zu Ihrem Warenkorb hinzugefügt."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
msgctxt "widget"
|
||||
msgid "Resume checkout"
|
||||
msgstr "Kauf fortsetzen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgctxt "widget"
|
||||
msgid "Redeem a voucher"
|
||||
msgstr "Gutschein einlösen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgctxt "widget"
|
||||
msgid "Redeem"
|
||||
msgstr "Einlösen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgctxt "widget"
|
||||
msgid "Voucher code"
|
||||
msgstr "Gutscheincode"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgctxt "widget"
|
||||
msgid "Close"
|
||||
msgstr "Schließen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgctxt "widget"
|
||||
msgid "Continue"
|
||||
msgstr "Fortfahren"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgctxt "widget"
|
||||
msgid "See variations"
|
||||
msgstr "Varianten zeigen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr "Andere Veranstaltung auswählen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different date"
|
||||
msgstr "Anderen Termin auswählen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr "Zurück"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr "Nächster Monat"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr "Vorheriger Monat"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgctxt "widget"
|
||||
msgid "Next week"
|
||||
msgstr "Nächste Woche"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgctxt "widget"
|
||||
msgid "Previous week"
|
||||
msgstr "Vorherige Woche"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgctxt "widget"
|
||||
msgid "Open seat selection"
|
||||
msgstr "Saalplan öffnen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"Some or all ticket categories are currently sold out. If you want, you can "
|
||||
@@ -883,84 +908,84 @@ msgid ""
|
||||
"again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgctxt "widget"
|
||||
msgid "Load more"
|
||||
msgstr "Mehr laden"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "Mo"
|
||||
msgstr "Mo"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "Tu"
|
||||
msgstr "Di"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "We"
|
||||
msgstr "Mi"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "Th"
|
||||
msgstr "Do"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:67
|
||||
msgid "Fr"
|
||||
msgstr "Fr"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
msgid "Sa"
|
||||
msgstr "Sa"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
msgid "Su"
|
||||
msgstr "So"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
msgid "January"
|
||||
msgstr "Januar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
msgid "February"
|
||||
msgstr "Februar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:70
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
msgid "March"
|
||||
msgstr "März"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:71
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
msgid "April"
|
||||
msgstr "April"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
msgid "May"
|
||||
msgstr "Mai"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
msgid "June"
|
||||
msgstr "Juni"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
msgid "July"
|
||||
msgstr "Juli"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
msgid "August"
|
||||
msgstr "August"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:80
|
||||
msgid "September"
|
||||
msgstr "September"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:81
|
||||
msgid "October"
|
||||
msgstr "Oktober"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:82
|
||||
msgid "November"
|
||||
msgstr "November"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:83
|
||||
msgid "December"
|
||||
msgstr "Dezember"
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ Badge
|
||||
Badges
|
||||
Bancontact
|
||||
Banking
|
||||
barcodes
|
||||
Bcc
|
||||
BCC
|
||||
Beispielevent
|
||||
@@ -143,6 +144,7 @@ Inc
|
||||
inkl
|
||||
innenname
|
||||
innennamen
|
||||
Input
|
||||
Installations
|
||||
integrationen
|
||||
INV
|
||||
@@ -183,6 +185,7 @@ Multibanco
|
||||
MwSt
|
||||
MyBank
|
||||
name
|
||||
NFC
|
||||
Nr
|
||||
NREI
|
||||
number
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-08 15:04+0000\n"
|
||||
"POT-Creation-Date: 2023-04-05 09:17+0000\n"
|
||||
"PO-Revision-Date: 2023-02-09 13:56+0000\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: German (informal) <https://translate.pretix.eu/projects/"
|
||||
@@ -495,49 +495,49 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr "Check-in-QR-Code"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:385
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:386
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "Die Hintergrund-PDF-Datei konnte nicht geladen werden:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:654
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:656
|
||||
msgid "Group of objects"
|
||||
msgstr "Gruppe von Objekten"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:660
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
msgid "Text object"
|
||||
msgstr "Text-Objekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
msgid "Barcode area"
|
||||
msgstr "QR-Code-Bereich"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
msgid "Image area"
|
||||
msgstr "Bildbereich"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Event-Ticketshop von pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:670
|
||||
msgid "Object"
|
||||
msgstr "Objekt"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:672
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:674
|
||||
msgid "Ticket design"
|
||||
msgstr "Ticket-Design"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:963
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:986
|
||||
msgid "Saving failed."
|
||||
msgstr "Speichern fehlgeschlagen."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1031
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1070
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1105
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
"Es gab ein Problem beim Hochladen der PDF-Datei, bitte erneut versuchen."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1088
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
"Möchtest du den Editor wirklich schließen ohne Ihre Änderungen zu speichern?"
|
||||
@@ -546,25 +546,25 @@ msgstr ""
|
||||
msgid "An error has occurred."
|
||||
msgstr "Ein Fehler ist aufgetreten."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:54
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:52
|
||||
msgid "Generating messages …"
|
||||
msgstr "Generiere Nachrichten…"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:107
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:109
|
||||
msgid "Unknown error."
|
||||
msgstr "Unbekannter Fehler."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:307
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:309
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "Diese Farbe hat einen sehr guten Kontrast und ist sehr gut zu lesen!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:311
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:313
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Diese Farbe hat einen ausreichenden Kontrast und ist wahrscheinlich gut zu "
|
||||
"lesen!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:315
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:317
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -572,32 +572,32 @@ msgstr ""
|
||||
"Diese Farbe hat einen schlechten Kontrast für Text auf einem weißen "
|
||||
"Hintergrund. Bitte wähle eine dunklere Farbe."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:464
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:486
|
||||
msgid "Search query"
|
||||
msgstr "Suchbegriff"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:482
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:483
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:485
|
||||
msgid "None"
|
||||
msgstr "Keine"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:487
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:489
|
||||
msgid "Selected only"
|
||||
msgstr "Nur ausgewählte"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:890
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:892
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Intern einen anderen Namen verwenden"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:926
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:932
|
||||
msgid "Click to close"
|
||||
msgstr "Klicken zum Schließen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:998
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:1007
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Du hast ungespeicherte Änderungen!"
|
||||
|
||||
@@ -681,82 +681,107 @@ msgstr "Deine lokale Zeit:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:17
|
||||
msgctxt "widget"
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
msgctxt "widget"
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#, fuzzy, javascript-format
|
||||
#| msgid "Selected only"
|
||||
msgctxt "widget"
|
||||
msgid "Select %s"
|
||||
msgstr "Nur ausgewählte"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#, fuzzy, javascript-format
|
||||
#| msgctxt "widget"
|
||||
#| msgid "See variations"
|
||||
msgctxt "widget"
|
||||
msgid "Select variant %s"
|
||||
msgstr "Varianten zeigen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "Sold out"
|
||||
msgstr "Ausverkauft"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "Buy"
|
||||
msgstr "In den Warenkorb"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
msgctxt "widget"
|
||||
msgid "Register"
|
||||
msgstr "Anmelden"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
msgctxt "widget"
|
||||
msgid "Reserved"
|
||||
msgstr "Reserviert"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
msgctxt "widget"
|
||||
msgid "FREE"
|
||||
msgstr "GRATIS"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
msgctxt "widget"
|
||||
msgid "from %(currency)s %(price)s"
|
||||
msgstr "ab %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
msgctxt "widget"
|
||||
msgid "incl. %(rate)s% %(taxname)s"
|
||||
msgstr "inkl. %(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
msgctxt "widget"
|
||||
msgid "plus %(rate)s% %(taxname)s"
|
||||
msgstr "zzgl. %(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr "inkl. Steuern"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr "zzgl. Steuern"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "currently available: %s"
|
||||
msgstr "aktuell verfügbar: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
msgctxt "widget"
|
||||
msgid "Only available with a voucher"
|
||||
msgstr "Nur mit Gutschein verfügbar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:33
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "minimum amount to order: %s"
|
||||
msgstr "minimale Bestellmenge: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
msgctxt "widget"
|
||||
msgid "Close ticket shop"
|
||||
msgstr "Ticket-Shop schließen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
msgctxt "widget"
|
||||
msgid "The ticket shop could not be loaded."
|
||||
msgstr "Der Ticket-Shop konnte nicht geladen werden."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"There are currently a lot of users in this ticket shop. Please open the shop "
|
||||
@@ -765,17 +790,17 @@ msgstr ""
|
||||
"Es sind derzeit sehr viele Benutzer in diesem Ticketshop. Bitte öffne diesen "
|
||||
"Ticketshop in einem neuen Tab um fortzufahren."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
msgctxt "widget"
|
||||
msgid "Open ticket shop"
|
||||
msgstr "Ticket-Shop öffnen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
msgctxt "widget"
|
||||
msgid "The cart could not be created. Please try again later"
|
||||
msgstr "Der Warenkorb konnte nicht erstellt werden. Bitte erneut versuchen."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:40
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"We could not create your cart, since there are currently too many users in "
|
||||
@@ -785,12 +810,12 @@ msgstr ""
|
||||
"diesem Ticketshop sind. Bitte klicke \"Weiter\" um es in einem neuen Tab "
|
||||
"erneut zu versuchen."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Waiting list"
|
||||
msgstr "Warteliste"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"You currently have an active cart for this event. If you select more "
|
||||
@@ -799,82 +824,82 @@ msgstr ""
|
||||
"Du hast einen aktiven Warenkorb für diese Veranstaltung. Wenn du mehr "
|
||||
"Produkte auswählst, werden diese zu deinem Warenkorb hinzugefügt."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
msgctxt "widget"
|
||||
msgid "Resume checkout"
|
||||
msgstr "Kauf fortsetzen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgctxt "widget"
|
||||
msgid "Redeem a voucher"
|
||||
msgstr "Gutschein einlösen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgctxt "widget"
|
||||
msgid "Redeem"
|
||||
msgstr "Einlösen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgctxt "widget"
|
||||
msgid "Voucher code"
|
||||
msgstr "Gutscheincode"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgctxt "widget"
|
||||
msgid "Close"
|
||||
msgstr "Schließen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgctxt "widget"
|
||||
msgid "Continue"
|
||||
msgstr "Fortfahren"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgctxt "widget"
|
||||
msgid "See variations"
|
||||
msgstr "Varianten zeigen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr "Andere Veranstaltung auswählen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different date"
|
||||
msgstr "Anderen Termin auswählen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr "Zurück"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr "Nächster Monat"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr "Vorheriger Monat"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgctxt "widget"
|
||||
msgid "Next week"
|
||||
msgstr "Nächste Woche"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgctxt "widget"
|
||||
msgid "Previous week"
|
||||
msgstr "Vorherige Woche"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgctxt "widget"
|
||||
msgid "Open seat selection"
|
||||
msgstr "Saalplan öffnen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"Some or all ticket categories are currently sold out. If you want, you can "
|
||||
@@ -882,84 +907,84 @@ msgid ""
|
||||
"again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgctxt "widget"
|
||||
msgid "Load more"
|
||||
msgstr "Mehr laden"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "Mo"
|
||||
msgstr "Mo"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "Tu"
|
||||
msgstr "Di"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "We"
|
||||
msgstr "Mi"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "Th"
|
||||
msgstr "Do"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:67
|
||||
msgid "Fr"
|
||||
msgstr "Fr"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
msgid "Sa"
|
||||
msgstr "Sa"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
msgid "Su"
|
||||
msgstr "So"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
msgid "January"
|
||||
msgstr "Januar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
msgid "February"
|
||||
msgstr "Februar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:70
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
msgid "March"
|
||||
msgstr "März"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:71
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
msgid "April"
|
||||
msgstr "April"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
msgid "May"
|
||||
msgstr "Mai"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
msgid "June"
|
||||
msgstr "Juni"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
msgid "July"
|
||||
msgstr "Juli"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
msgid "August"
|
||||
msgstr "August"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:80
|
||||
msgid "September"
|
||||
msgstr "September"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:81
|
||||
msgid "October"
|
||||
msgstr "Oktober"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:82
|
||||
msgid "November"
|
||||
msgstr "November"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:83
|
||||
msgid "December"
|
||||
msgstr "Dezember"
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ Badge
|
||||
Badges
|
||||
Bancontact
|
||||
Banking
|
||||
barcodes
|
||||
Bcc
|
||||
BCC
|
||||
Beispielevent
|
||||
@@ -143,6 +144,7 @@ Inc
|
||||
inkl
|
||||
innenname
|
||||
innennamen
|
||||
Input
|
||||
Installations
|
||||
integrationen
|
||||
INV
|
||||
@@ -183,6 +185,7 @@ Multibanco
|
||||
MwSt
|
||||
MyBank
|
||||
name
|
||||
NFC
|
||||
Nr
|
||||
NREI
|
||||
number
|
||||
|
||||
+2485
-2119
File diff suppressed because it is too large
Load Diff
+104
-82
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-08 15:04+0000\n"
|
||||
"POT-Creation-Date: 2023-04-05 09:17+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -480,48 +480,48 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:385
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:386
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:654
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:656
|
||||
msgid "Group of objects"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:660
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
msgid "Text object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
msgid "Barcode area"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
msgid "Image area"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
msgid "Powered by pretix"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:670
|
||||
msgid "Object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:672
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:674
|
||||
msgid "Ticket design"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:963
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:986
|
||||
msgid "Saving failed."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1031
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1070
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1105
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1088
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
|
||||
@@ -529,54 +529,54 @@ msgstr ""
|
||||
msgid "An error has occurred."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:54
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:52
|
||||
msgid "Generating messages …"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:107
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:109
|
||||
msgid "Unknown error."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:307
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:309
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:311
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:313
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:315
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:317
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:464
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:486
|
||||
msgid "Search query"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:482
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:483
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:485
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:487
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:489
|
||||
msgid "Selected only"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:890
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:892
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:926
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:932
|
||||
msgid "Click to close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:998
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:1007
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
@@ -655,193 +655,215 @@ msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:17
|
||||
msgctxt "widget"
|
||||
msgid "Sold out"
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
msgctxt "widget"
|
||||
msgid "Buy"
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Register"
|
||||
msgid "Select %s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Reserved"
|
||||
msgid "Select variant %s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "FREE"
|
||||
msgid "Sold out"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "from %(currency)s %(price)s"
|
||||
msgid "Buy"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
msgctxt "widget"
|
||||
msgid "incl. %(rate)s% %(taxname)s"
|
||||
msgid "Register"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
msgctxt "widget"
|
||||
msgid "plus %(rate)s% %(taxname)s"
|
||||
msgid "Reserved"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgid "FREE"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgid "from %(currency)s %(price)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
msgctxt "widget"
|
||||
msgid "incl. %(rate)s% %(taxname)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
msgctxt "widget"
|
||||
msgid "plus %(rate)s% %(taxname)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "currently available: %s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
msgctxt "widget"
|
||||
msgid "Only available with a voucher"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:33
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "minimum amount to order: %s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
msgctxt "widget"
|
||||
msgid "Close ticket shop"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
msgctxt "widget"
|
||||
msgid "The ticket shop could not be loaded."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"There are currently a lot of users in this ticket shop. Please open the shop "
|
||||
"in a new tab to continue."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
msgctxt "widget"
|
||||
msgid "Open ticket shop"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
msgctxt "widget"
|
||||
msgid "The cart could not be created. Please try again later"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:40
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"We could not create your cart, since there are currently too many users in "
|
||||
"this ticket shop. Please click \"Continue\" to retry in a new tab."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Waiting list"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"You currently have an active cart for this event. If you select more "
|
||||
"products, they will be added to your existing cart."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
msgctxt "widget"
|
||||
msgid "Resume checkout"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgctxt "widget"
|
||||
msgid "Redeem a voucher"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgctxt "widget"
|
||||
msgid "Redeem"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgctxt "widget"
|
||||
msgid "Voucher code"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgctxt "widget"
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgctxt "widget"
|
||||
msgid "Continue"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgctxt "widget"
|
||||
msgid "See variations"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different date"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgctxt "widget"
|
||||
msgid "Next week"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgctxt "widget"
|
||||
msgid "Previous week"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgctxt "widget"
|
||||
msgid "Open seat selection"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"Some or all ticket categories are currently sold out. If you want, you can "
|
||||
@@ -849,83 +871,83 @@ msgid ""
|
||||
"again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgctxt "widget"
|
||||
msgid "Load more"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "Mo"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "Tu"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "We"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "Th"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:67
|
||||
msgid "Fr"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
msgid "Sa"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
msgid "Su"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
msgid "January"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
msgid "February"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:70
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
msgid "March"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:71
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
msgid "April"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
msgid "May"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
msgid "June"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
msgid "July"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
msgid "August"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:80
|
||||
msgid "September"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:81
|
||||
msgid "October"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:82
|
||||
msgid "November"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:83
|
||||
msgid "December"
|
||||
msgstr ""
|
||||
|
||||
+2496
-2051
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-08 15:04+0000\n"
|
||||
"POT-Creation-Date: 2023-04-05 09:17+0000\n"
|
||||
"PO-Revision-Date: 2019-10-03 19:00+0000\n"
|
||||
"Last-Translator: Chris Spy <chrispiropoulou@hotmail.com>\n"
|
||||
"Language-Team: Greek <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -530,51 +530,51 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr "Έλεγχος QR"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:385
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:386
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
"Το αρχείο φόντου PDF δεν ήταν δυνατό να φορτωθεί για τον ακόλουθο λόγο:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:654
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:656
|
||||
msgid "Group of objects"
|
||||
msgstr "Ομάδα αντικειμένων"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:660
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
msgid "Text object"
|
||||
msgstr "Αντικείμενο κειμένου"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
msgid "Barcode area"
|
||||
msgstr "Περιοχή Barcode"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
#, fuzzy
|
||||
#| msgid "Barcode area"
|
||||
msgid "Image area"
|
||||
msgstr "Περιοχή Barcode"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Υποστηρίζεται από το Pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:670
|
||||
msgid "Object"
|
||||
msgstr "Αντικείμενο"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:672
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:674
|
||||
msgid "Ticket design"
|
||||
msgstr "Σχεδιασμός εισιτηρίων"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:963
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:986
|
||||
msgid "Saving failed."
|
||||
msgstr "Η αποθήκευση απέτυχε."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1031
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1070
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1105
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr "Σφάλμα κατά τη μεταφόρτωση του αρχείου PDF, δοκιμάστε ξανά."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1088
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
"Θέλετε πραγματικά να αφήσετε τον επεξεργαστή χωρίς να αποθηκεύσετε τις "
|
||||
@@ -584,26 +584,26 @@ msgstr ""
|
||||
msgid "An error has occurred."
|
||||
msgstr "Παρουσιάστηκε σφάλμα."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:54
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:52
|
||||
msgid "Generating messages …"
|
||||
msgstr "Δημιουργία μηνυμάτων …"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:107
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:109
|
||||
msgid "Unknown error."
|
||||
msgstr "Άγνωστο σφάλμα."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:307
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:309
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
"Το χρώμα σας έχει μεγάλη αντίθεση και είναι πολύ εύκολο να το διαβάσετε!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:311
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:313
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Το χρώμα σας έχει αξιοπρεπή αντίθεση και είναι ίσως αρκετά καλό για να "
|
||||
"διαβάσετε!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:315
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:317
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -611,32 +611,32 @@ msgstr ""
|
||||
"Το χρώμα σας έχει κακή αντίθεση για κείμενο σε λευκό φόντο, επιλέξτε μια πιο "
|
||||
"σκούρα σκιά."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:464
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:486
|
||||
msgid "Search query"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:482
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
msgid "All"
|
||||
msgstr "Όλα"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:483
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:485
|
||||
msgid "None"
|
||||
msgstr "Κανένας"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:487
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:489
|
||||
msgid "Selected only"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:890
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:892
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Χρησιμοποιήστε διαφορετικό όνομα εσωτερικά"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:926
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:932
|
||||
msgid "Click to close"
|
||||
msgstr "Κάντε κλικ για να κλείσετε"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:998
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:1007
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
@@ -729,89 +729,113 @@ msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:17
|
||||
msgctxt "widget"
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
msgctxt "widget"
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Select %s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#, fuzzy, javascript-format
|
||||
#| msgctxt "widget"
|
||||
#| msgid "See variations"
|
||||
msgctxt "widget"
|
||||
msgid "Select variant %s"
|
||||
msgstr "Δείτε παραλλαγές"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "Sold out"
|
||||
msgstr "Εξαντλημένα"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "Buy"
|
||||
msgstr "Αγορά"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
msgctxt "widget"
|
||||
msgid "Register"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
msgctxt "widget"
|
||||
msgid "Reserved"
|
||||
msgstr "Κατοχυρωμένα"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
msgctxt "widget"
|
||||
msgid "FREE"
|
||||
msgstr "ΔΩΡΕΑΝ"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
msgctxt "widget"
|
||||
msgid "from %(currency)s %(price)s"
|
||||
msgstr "απο %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
msgctxt "widget"
|
||||
msgid "incl. %(rate)s% %(taxname)s"
|
||||
msgstr "συμπεριλαμβανομένου %(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
msgctxt "widget"
|
||||
msgid "plus %(rate)s% %(taxname)s"
|
||||
msgstr "συν %(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr "συμπεριλαμβανομένων των φόρων"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr "συν τους φόρους"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "currently available: %s"
|
||||
msgstr "διαθέσιμη προς το παρόν:%s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
msgctxt "widget"
|
||||
msgid "Only available with a voucher"
|
||||
msgstr "Διατίθεται μόνο με ένα κουπόνι"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:33
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "minimum amount to order: %s"
|
||||
msgstr "ελάχιστο ποσό για παραγγελία: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
msgctxt "widget"
|
||||
msgid "Close ticket shop"
|
||||
msgstr "Κλείστε το κατάστημα εισιτηρίων"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
msgctxt "widget"
|
||||
msgid "The ticket shop could not be loaded."
|
||||
msgstr "Δεν ήταν δυνατή η φόρτωση του εισιτηρίου."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"There are currently a lot of users in this ticket shop. Please open the shop "
|
||||
"in a new tab to continue."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "Close ticket shop"
|
||||
@@ -819,25 +843,25 @@ msgctxt "widget"
|
||||
msgid "Open ticket shop"
|
||||
msgstr "Κλείστε το κατάστημα εισιτηρίων"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
msgctxt "widget"
|
||||
msgid "The cart could not be created. Please try again later"
|
||||
msgstr ""
|
||||
"Δεν ήταν δυνατή η δημιουργία του καλαθιού. Παρακαλώ προσπαθήστε ξανά αργότερα"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:40
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"We could not create your cart, since there are currently too many users in "
|
||||
"this ticket shop. Please click \"Continue\" to retry in a new tab."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Waiting list"
|
||||
msgstr "Λίστα αναμονής"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"You currently have an active cart for this event. If you select more "
|
||||
@@ -846,72 +870,72 @@ msgstr ""
|
||||
"Αυτήν τη στιγμή έχετε προϊόντα στο καλάθι για αυτήν την εκδήλωση. Αν "
|
||||
"επιλέξετε περισσότερα προϊόντα, θα προστεθούν στο υπάρχον καλάθι σας."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
msgctxt "widget"
|
||||
msgid "Resume checkout"
|
||||
msgstr "Συνεχίστε την ολοκλήρωση της αγοράς"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgctxt "widget"
|
||||
msgid "Redeem a voucher"
|
||||
msgstr "Εξαργυρώστε ένα κουπόνι"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgctxt "widget"
|
||||
msgid "Redeem"
|
||||
msgstr "Εξαργυρώστε"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgctxt "widget"
|
||||
msgid "Voucher code"
|
||||
msgstr "Κωδικός κουπονιού"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgctxt "widget"
|
||||
msgid "Close"
|
||||
msgstr "Κλείσιμο"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgctxt "widget"
|
||||
msgid "Continue"
|
||||
msgstr "Συνέχεια"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgctxt "widget"
|
||||
msgid "See variations"
|
||||
msgstr "Δείτε παραλλαγές"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr "Επιλέξτε διαφορετική εκδήλωση"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different date"
|
||||
msgstr "Επιλέξτε διαφορετική ημερομηνία"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr "Πίσω"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr "Επόμενος μήνας"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr "Προηγούμενος μήνας"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgctxt "widget"
|
||||
msgid "Next week"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "Previous month"
|
||||
@@ -919,12 +943,12 @@ msgctxt "widget"
|
||||
msgid "Previous week"
|
||||
msgstr "Προηγούμενος μήνας"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgctxt "widget"
|
||||
msgid "Open seat selection"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"Some or all ticket categories are currently sold out. If you want, you can "
|
||||
@@ -932,84 +956,84 @@ msgid ""
|
||||
"again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgctxt "widget"
|
||||
msgid "Load more"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "Mo"
|
||||
msgstr "Δευ"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "Tu"
|
||||
msgstr "Τρι"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "We"
|
||||
msgstr "Τετ"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "Th"
|
||||
msgstr "Πεμ"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:67
|
||||
msgid "Fr"
|
||||
msgstr "Παρ"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
msgid "Sa"
|
||||
msgstr "Σαβ"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
msgid "Su"
|
||||
msgstr "Κυρ"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
msgid "January"
|
||||
msgstr "Ιανουάριος"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
msgid "February"
|
||||
msgstr "Φεβρουάριος"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:70
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
msgid "March"
|
||||
msgstr "Μάρτιος"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:71
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
msgid "April"
|
||||
msgstr "Απρίλιος"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
msgid "May"
|
||||
msgstr "Μάιος"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
msgid "June"
|
||||
msgstr "Ιούνιος"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
msgid "July"
|
||||
msgstr "Ιούλιος"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
msgid "August"
|
||||
msgstr "Αύγουστος"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:80
|
||||
msgid "September"
|
||||
msgstr "Σεπτέμβριος"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:81
|
||||
msgid "October"
|
||||
msgstr "Οκτώβριος"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:82
|
||||
msgid "November"
|
||||
msgstr "Νοέμβριος"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:83
|
||||
msgid "December"
|
||||
msgstr "Δεκέμβριος"
|
||||
|
||||
|
||||
+2498
-2049
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-08 15:04+0000\n"
|
||||
"POT-Creation-Date: 2023-04-05 09:17+0000\n"
|
||||
"PO-Revision-Date: 2021-11-25 21:00+0000\n"
|
||||
"Last-Translator: Ismael Menéndez Fernández <ismael.menendez@balidea.com>\n"
|
||||
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -499,51 +499,51 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr "QR de Chequeo"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:385
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:386
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
"El archivo PDF de fondo no ha podido ser cargado debido al siguiente motivo:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:654
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:656
|
||||
msgid "Group of objects"
|
||||
msgstr "Grupo de objetos"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:660
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
msgid "Text object"
|
||||
msgstr "Objeto de texto"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
msgid "Barcode area"
|
||||
msgstr "Área para código de barras"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
msgid "Image area"
|
||||
msgstr "Área de imagen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Proveído por pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:670
|
||||
msgid "Object"
|
||||
msgstr "Objeto"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:672
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:674
|
||||
msgid "Ticket design"
|
||||
msgstr "Diseño del ticket"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:963
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:986
|
||||
msgid "Saving failed."
|
||||
msgstr "El guardado falló."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1031
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1070
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1105
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
"Ha habido un error mientras se cargaba el archivo PDF, por favor, intente de "
|
||||
"nuevo."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1088
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr "¿Realmente desea salir del editor sin haber guardado sus cambios?"
|
||||
|
||||
@@ -551,25 +551,25 @@ msgstr "¿Realmente desea salir del editor sin haber guardado sus cambios?"
|
||||
msgid "An error has occurred."
|
||||
msgstr "Ha ocurrido un error."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:54
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:52
|
||||
msgid "Generating messages …"
|
||||
msgstr "Generando mensajes…"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:107
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:109
|
||||
msgid "Unknown error."
|
||||
msgstr "Error desconocido."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:307
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:309
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "¡Tu color tiene gran contraste y es muy fácil de leer!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:311
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:313
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"¡Tu color tiene un contraste decente y es probablemente lo suficientemente "
|
||||
"legible!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:315
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:317
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -577,32 +577,32 @@ msgstr ""
|
||||
"Tu color tiene mal contraste para un texto con fondo blanco, por favor, "
|
||||
"escoge un tono más oscuro."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:464
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:486
|
||||
msgid "Search query"
|
||||
msgstr "Consultar búsqueda"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:482
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
msgid "All"
|
||||
msgstr "Todos"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:483
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:485
|
||||
msgid "None"
|
||||
msgstr "Ninguno"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:487
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:489
|
||||
msgid "Selected only"
|
||||
msgstr "Solamente seleccionados"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:890
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:892
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Usar un nombre diferente internamente"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:926
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:932
|
||||
msgid "Click to close"
|
||||
msgstr "Click para cerrar"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:998
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:1007
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "¡Tienes cambios sin guardar!"
|
||||
|
||||
@@ -685,82 +685,107 @@ msgstr "Su hora local:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:17
|
||||
msgctxt "widget"
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
msgctxt "widget"
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#, fuzzy, javascript-format
|
||||
#| msgid "Selected only"
|
||||
msgctxt "widget"
|
||||
msgid "Select %s"
|
||||
msgstr "Solamente seleccionados"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#, fuzzy, javascript-format
|
||||
#| msgctxt "widget"
|
||||
#| msgid "See variations"
|
||||
msgctxt "widget"
|
||||
msgid "Select variant %s"
|
||||
msgstr "Ver variaciones"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "Sold out"
|
||||
msgstr "Agotado"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "Buy"
|
||||
msgstr "Comprar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
msgctxt "widget"
|
||||
msgid "Register"
|
||||
msgstr "Registrarse"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
msgctxt "widget"
|
||||
msgid "Reserved"
|
||||
msgstr "Reservado"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
msgctxt "widget"
|
||||
msgid "FREE"
|
||||
msgstr "GRATIS"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
msgctxt "widget"
|
||||
msgid "from %(currency)s %(price)s"
|
||||
msgstr "desde %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
msgctxt "widget"
|
||||
msgid "incl. %(rate)s% %(taxname)s"
|
||||
msgstr "incluye %(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
msgctxt "widget"
|
||||
msgid "plus %(rate)s% %(taxname)s"
|
||||
msgstr "más %(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr "incl. impuestos"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr "más impuestos"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "currently available: %s"
|
||||
msgstr "disponible actualmente: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
msgctxt "widget"
|
||||
msgid "Only available with a voucher"
|
||||
msgstr "Solo disponible mediante voucher"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:33
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "minimum amount to order: %s"
|
||||
msgstr "cantidad mínima a ordenar: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
msgctxt "widget"
|
||||
msgid "Close ticket shop"
|
||||
msgstr "Cerrar tienda de tickets"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
msgctxt "widget"
|
||||
msgid "The ticket shop could not be loaded."
|
||||
msgstr "No se ha podido cargar la tienda de tickets."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"There are currently a lot of users in this ticket shop. Please open the shop "
|
||||
@@ -769,19 +794,19 @@ msgstr ""
|
||||
"Actualmente hay muchos usuarios en la tienda de tickets. Por favor abra la "
|
||||
"tienda en una nueva pestaña para continuar."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
msgctxt "widget"
|
||||
msgid "Open ticket shop"
|
||||
msgstr "Abrir tienda de tickets"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
msgctxt "widget"
|
||||
msgid "The cart could not be created. Please try again later"
|
||||
msgstr ""
|
||||
"El carrito de compras no ha podido crearse. Por favor, intente de nuevo más "
|
||||
"tarde"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:40
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"We could not create your cart, since there are currently too many users in "
|
||||
@@ -790,12 +815,12 @@ msgstr ""
|
||||
"No pudimos crear su carrito debido a que hay muchos usuarios en la tienda. "
|
||||
"Por favor, presione \"Continuar\" para intentarlo en una nueva pestaña."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Waiting list"
|
||||
msgstr "Lista de espera"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"You currently have an active cart for this event. If you select more "
|
||||
@@ -804,82 +829,82 @@ msgstr ""
|
||||
"Ya tiene un carrito de compras activo para este evento. Si selecciona más "
|
||||
"productos, estos serán añadidos al carrito actual."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
msgctxt "widget"
|
||||
msgid "Resume checkout"
|
||||
msgstr "Continuar pago"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgctxt "widget"
|
||||
msgid "Redeem a voucher"
|
||||
msgstr "Canjear un cupón"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgctxt "widget"
|
||||
msgid "Redeem"
|
||||
msgstr "Canjear"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgctxt "widget"
|
||||
msgid "Voucher code"
|
||||
msgstr "Código del cupón"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgctxt "widget"
|
||||
msgid "Close"
|
||||
msgstr "Cerrar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgctxt "widget"
|
||||
msgid "Continue"
|
||||
msgstr "Continuar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgctxt "widget"
|
||||
msgid "See variations"
|
||||
msgstr "Ver variaciones"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr "Eligir un evento diferente"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different date"
|
||||
msgstr "Elegir una fecha diferente"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr "Atrás"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr "Siguiente mes"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr "Mes anterior"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgctxt "widget"
|
||||
msgid "Next week"
|
||||
msgstr "Semana siguiente"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgctxt "widget"
|
||||
msgid "Previous week"
|
||||
msgstr "Semana anterior"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgctxt "widget"
|
||||
msgid "Open seat selection"
|
||||
msgstr "Abrir selección de asientos"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"Some or all ticket categories are currently sold out. If you want, you can "
|
||||
@@ -887,84 +912,84 @@ msgid ""
|
||||
"again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgctxt "widget"
|
||||
msgid "Load more"
|
||||
msgstr "Cargar más"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "Mo"
|
||||
msgstr "Lun"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "Tu"
|
||||
msgstr "Mar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "We"
|
||||
msgstr "Mié"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "Th"
|
||||
msgstr "Jue"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:67
|
||||
msgid "Fr"
|
||||
msgstr "Vie"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
msgid "Sa"
|
||||
msgstr "Sáb"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
msgid "Su"
|
||||
msgstr "Dom"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
msgid "January"
|
||||
msgstr "Enero"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
msgid "February"
|
||||
msgstr "Febrero"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:70
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
msgid "March"
|
||||
msgstr "Marzo"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:71
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
msgid "April"
|
||||
msgstr "Abril"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
msgid "May"
|
||||
msgstr "Mayo"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
msgid "June"
|
||||
msgstr "Junio"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
msgid "July"
|
||||
msgstr "Julio"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
msgid "August"
|
||||
msgstr "Agosto"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:80
|
||||
msgid "September"
|
||||
msgstr "Septiembre"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:81
|
||||
msgid "October"
|
||||
msgstr "Octubre"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:82
|
||||
msgid "November"
|
||||
msgstr "Noviembre"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:83
|
||||
msgid "December"
|
||||
msgstr "Diciembre"
|
||||
|
||||
|
||||
+2480
-2067
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-08 15:04+0000\n"
|
||||
"POT-Creation-Date: 2023-04-05 09:17+0000\n"
|
||||
"PO-Revision-Date: 2021-11-10 05:00+0000\n"
|
||||
"Last-Translator: Jaakko Rinta-Filppula <jaakko@r-f.fi>\n"
|
||||
"Language-Team: Finnish <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -503,50 +503,50 @@ msgstr ""
|
||||
msgid "Check-in QR"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:385
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:386
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:654
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:656
|
||||
msgid "Group of objects"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:660
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
msgid "Text object"
|
||||
msgstr "Tekstiobjekti"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:662
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
msgid "Barcode area"
|
||||
msgstr "Viivakoodialue"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:664
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
#, fuzzy
|
||||
#| msgid "Barcode area"
|
||||
msgid "Image area"
|
||||
msgstr "Viivakoodialue"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:666
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
msgid "Powered by pretix"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:668
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:670
|
||||
msgid "Object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:672
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:674
|
||||
msgid "Ticket design"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:963
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:986
|
||||
msgid "Saving failed."
|
||||
msgstr "Tallennus epäonnistui."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1031
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1070
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1105
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1055
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:1088
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
|
||||
@@ -554,54 +554,54 @@ msgstr ""
|
||||
msgid "An error has occurred."
|
||||
msgstr "Tapahtui virhe."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:54
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:52
|
||||
msgid "Generating messages …"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:107
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:109
|
||||
msgid "Unknown error."
|
||||
msgstr "Tuntematon virhe."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:307
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:309
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:311
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:313
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:315
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:317
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:464
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:466
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:486
|
||||
msgid "Search query"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:482
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:484
|
||||
msgid "All"
|
||||
msgstr "Kaikki"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:483
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:485
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:487
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:489
|
||||
msgid "Selected only"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:890
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:892
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Käytä toista nimeä sisäisesti"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:926
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:932
|
||||
msgid "Click to close"
|
||||
msgstr "Sulje klikkaamalla"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:998
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:1007
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Sinulla on tallentamattomia muutoksia!"
|
||||
|
||||
@@ -686,89 +686,113 @@ msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:17
|
||||
msgctxt "widget"
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
msgctxt "widget"
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Select %s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#, fuzzy, javascript-format
|
||||
#| msgctxt "widget"
|
||||
#| msgid "See variations"
|
||||
msgctxt "widget"
|
||||
msgid "Select variant %s"
|
||||
msgstr "Näytä vaihtoehdot"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "Sold out"
|
||||
msgstr "Loppuunmyyty"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "Buy"
|
||||
msgstr "Osta"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
msgctxt "widget"
|
||||
msgid "Register"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
msgctxt "widget"
|
||||
msgid "Reserved"
|
||||
msgstr "Varattu"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
msgctxt "widget"
|
||||
msgid "FREE"
|
||||
msgstr "ILMAINEN"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
msgctxt "widget"
|
||||
msgid "from %(currency)s %(price)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
msgctxt "widget"
|
||||
msgid "incl. %(rate)s% %(taxname)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
msgctxt "widget"
|
||||
msgid "plus %(rate)s% %(taxname)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr "sis. verot"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "currently available: %s"
|
||||
msgstr "nyt saatavilla: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
msgctxt "widget"
|
||||
msgid "Only available with a voucher"
|
||||
msgstr "Saatavilla vain kupongilla"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:33
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "minimum amount to order: %s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
msgctxt "widget"
|
||||
msgid "Close ticket shop"
|
||||
msgstr "Sulje lippukauppa"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
msgctxt "widget"
|
||||
msgid "The ticket shop could not be loaded."
|
||||
msgstr "Lippukauppaa ei voitu ladata."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"There are currently a lot of users in this ticket shop. Please open the shop "
|
||||
"in a new tab to continue."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "Close ticket shop"
|
||||
@@ -776,106 +800,106 @@ msgctxt "widget"
|
||||
msgid "Open ticket shop"
|
||||
msgstr "Sulje lippukauppa"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
msgctxt "widget"
|
||||
msgid "The cart could not be created. Please try again later"
|
||||
msgstr "Ostoskoria ei voitu luoda. Ole hyvä ja yritä myöhemmin uudelleen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:40
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"We could not create your cart, since there are currently too many users in "
|
||||
"this ticket shop. Please click \"Continue\" to retry in a new tab."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Waiting list"
|
||||
msgstr "Jonotuslista"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"You currently have an active cart for this event. If you select more "
|
||||
"products, they will be added to your existing cart."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
msgctxt "widget"
|
||||
msgid "Resume checkout"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgctxt "widget"
|
||||
msgid "Redeem a voucher"
|
||||
msgstr "Käytä kuponki"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgctxt "widget"
|
||||
msgid "Redeem"
|
||||
msgstr "Käytä"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgctxt "widget"
|
||||
msgid "Voucher code"
|
||||
msgstr "Kuponkikoodi"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgctxt "widget"
|
||||
msgid "Close"
|
||||
msgstr "Sulje"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgctxt "widget"
|
||||
msgid "Continue"
|
||||
msgstr "Jatka"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgctxt "widget"
|
||||
msgid "See variations"
|
||||
msgstr "Näytä vaihtoehdot"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr "Valitse toinen tapahtuma"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different date"
|
||||
msgstr "Valitse toinen päivämäärä"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr "Takaisin"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr "Seuraava kuukausi"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr "Edellinen kuukausi"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:53
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgctxt "widget"
|
||||
msgid "Next week"
|
||||
msgstr "Seuraava viikko"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgctxt "widget"
|
||||
msgid "Previous week"
|
||||
msgstr "Edellinen viikko"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgctxt "widget"
|
||||
msgid "Open seat selection"
|
||||
msgstr "Avaa paikkavalinta"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"Some or all ticket categories are currently sold out. If you want, you can "
|
||||
@@ -883,84 +907,84 @@ msgid ""
|
||||
"again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgctxt "widget"
|
||||
msgid "Load more"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "Mo"
|
||||
msgstr "Ma"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "Tu"
|
||||
msgstr "Ti"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "We"
|
||||
msgstr "Ke"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "Th"
|
||||
msgstr "To"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:67
|
||||
msgid "Fr"
|
||||
msgstr "Pe"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
msgid "Sa"
|
||||
msgstr "La"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
msgid "Su"
|
||||
msgstr "Su"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:68
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
msgid "January"
|
||||
msgstr "Tammikuu"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:69
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
msgid "February"
|
||||
msgstr "Helmikuu"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:70
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
msgid "March"
|
||||
msgstr "Maaliskuu"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:71
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
msgid "April"
|
||||
msgstr "Huhtikuu"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
msgid "May"
|
||||
msgstr "Toukokuu"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:73
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
msgid "June"
|
||||
msgstr "Kesäkuu"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
msgid "July"
|
||||
msgstr "Heinäkuu"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
msgid "August"
|
||||
msgstr "Elokuu"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:80
|
||||
msgid "September"
|
||||
msgstr "Syyskuu"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:77
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:81
|
||||
msgid "October"
|
||||
msgstr "Lokakuu"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:82
|
||||
msgid "November"
|
||||
msgstr "Marraskuu"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:79
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:83
|
||||
msgid "December"
|
||||
msgstr "Joulukuu"
|
||||
|
||||
|
||||
+2483
-2047
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user