mirror of
https://github.com/pretix/pretix.git
synced 2026-01-21 00:02:26 +00:00
Compare commits
63 Commits
release/3.
...
docker-ngi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37f48ffd49 | ||
|
|
a5e41aae50 | ||
|
|
54e4ad1a1c | ||
|
|
b6e4163c2b | ||
|
|
1aa1583eae | ||
|
|
fc210cf06d | ||
|
|
3459f3e4c4 | ||
|
|
903a7f122d | ||
|
|
246d150511 | ||
|
|
2cd5094393 | ||
|
|
a665836a60 | ||
|
|
e7d2d0ddab | ||
|
|
1d722da5af | ||
|
|
90475e4159 | ||
|
|
3690dba73b | ||
|
|
0a55fdbc49 | ||
|
|
eac32c25ba | ||
|
|
c2345d200a | ||
|
|
663fd8a57a | ||
|
|
a204302910 | ||
|
|
13e464bcf1 | ||
|
|
8b2b98c128 | ||
|
|
a5f806d975 | ||
|
|
b51bd2118e | ||
|
|
089938c3ee | ||
|
|
574fe9094c | ||
|
|
6fdd32de6a | ||
|
|
b3e95f54dd | ||
|
|
55d8639ecc | ||
|
|
978130551a | ||
|
|
a452bf816c | ||
|
|
99c3981e2d | ||
|
|
87a514ca8b | ||
|
|
937b967259 | ||
|
|
242bfc0023 | ||
|
|
eed309636f | ||
|
|
0944929818 | ||
|
|
2592b8b221 | ||
|
|
fcdd852860 | ||
|
|
f43585bf36 | ||
|
|
5a034f1339 | ||
|
|
0eb5b73502 | ||
|
|
41e878fabb | ||
|
|
93a7c5df09 | ||
|
|
c71c78cf69 | ||
|
|
66af5973ec | ||
|
|
921b28f8d4 | ||
|
|
0aa5df8a17 | ||
|
|
65f6da8d9e | ||
|
|
827afd6d39 | ||
|
|
97561819e2 | ||
|
|
d02e8b1dcf | ||
|
|
7ad46addee | ||
|
|
956b6f43e4 | ||
|
|
cc493968a1 | ||
|
|
fd6fb52a11 | ||
|
|
ef11084613 | ||
|
|
2a85f327fd | ||
|
|
bd9d8ce0ad | ||
|
|
d71db5a8ad | ||
|
|
755d1b5692 | ||
|
|
0fad2ab728 | ||
|
|
2b9461e847 |
@@ -24,8 +24,8 @@ http {
|
||||
default_type application/octet-stream;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
|
||||
access_log /var/log/nginx/access.log private;
|
||||
error_log /var/log/nginx/error.log;
|
||||
access_log /dev/stdout private;
|
||||
error_log /dev/stderr;
|
||||
add_header Referrer-Policy same-origin;
|
||||
|
||||
gzip on;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
file=/tmp/supervisor.sock
|
||||
|
||||
[supervisord]
|
||||
logfile=/tmp/supervisord.log
|
||||
logfile_maxbytes=50MB
|
||||
logfile=/dev/stderr
|
||||
logfile_maxbytes=0
|
||||
logfile_backups=10
|
||||
loglevel=info
|
||||
pidfile=/tmp/supervisord.pid
|
||||
|
||||
@@ -5,3 +5,7 @@ autorestart=true
|
||||
priority=10
|
||||
stdout_events_enabled=true
|
||||
stderr_events_enabled=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
@@ -4,3 +4,7 @@ autostart=true
|
||||
autorestart=true
|
||||
priority=5
|
||||
user=pretixuser
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
@@ -5,3 +5,7 @@ autorestart=true
|
||||
priority=5
|
||||
user=pretixuser
|
||||
environment=HOME=/pretix
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
@@ -47,6 +47,8 @@ item_meta_properties object Item-specific m
|
||||
valid_keys object Cryptographic keys for non-default signature schemes.
|
||||
For performance reason, value is omitted in lists and
|
||||
only contained in detail views. Value can be cached.
|
||||
sales_channels list A list of sales channels this event is available for
|
||||
sale on.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
@@ -91,6 +93,11 @@ valid_keys object Cryptographic k
|
||||
|
||||
The attribute ``valid_keys`` has been added.
|
||||
|
||||
.. versionchanged:: 3.14
|
||||
|
||||
The attribute ``sales_channels`` has been added.
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
@@ -147,11 +154,16 @@ Endpoints
|
||||
"timezone": "Europe/Berlin",
|
||||
"item_meta_properties": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.banktransfer"
|
||||
"pretix.plugins.stripe"
|
||||
"pretix.plugins.paypal"
|
||||
"pretix.plugins.banktransfer",
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal",
|
||||
"pretix.plugins.ticketoutputpdf"
|
||||
],
|
||||
"sales_channels": [
|
||||
"web",
|
||||
"pretixpos",
|
||||
"resellers"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -170,6 +182,7 @@ Endpoints
|
||||
only contain the events matching the set criteria. Providing ``?attr[Format]=Seminar`` would return only those
|
||||
events having set their ``Format`` meta data to ``Seminar``, ``?attr[Format]=`` only those, that have no value
|
||||
set. Please note that this filter will respect default values set on organizer level.
|
||||
:query sales_channel: If set to a sales channel identifier, only events allowed to be sold on the specified sales channel are returned.
|
||||
:param organizer: The ``slug`` field of a valid organizer
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
@@ -219,16 +232,21 @@ Endpoints
|
||||
"timezone": "Europe/Berlin",
|
||||
"item_meta_properties": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.banktransfer"
|
||||
"pretix.plugins.stripe"
|
||||
"pretix.plugins.paypal"
|
||||
"pretix.plugins.banktransfer",
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal",
|
||||
"pretix.plugins.ticketoutputpdf"
|
||||
],
|
||||
"valid_keys": {
|
||||
"pretix_sig1": [
|
||||
"LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUNvd0JRWURLMlZ3QXlFQTdBRDcvdkZBMzNFc1k0ejJQSHI3aVpQc1o4bjVkaDBhalA4Z3l6Tm1tSXM9Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo="
|
||||
]
|
||||
}
|
||||
},
|
||||
"sales_channels": [
|
||||
"web",
|
||||
"pretixpos",
|
||||
"resellers"
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
@@ -279,6 +297,11 @@ Endpoints
|
||||
"plugins": [
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
],
|
||||
"sales_channels": [
|
||||
"web",
|
||||
"pretixpos",
|
||||
"resellers"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -314,6 +337,11 @@ Endpoints
|
||||
"plugins": [
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
],
|
||||
"sales_channels": [
|
||||
"web",
|
||||
"pretixpos",
|
||||
"resellers"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -369,6 +397,11 @@ Endpoints
|
||||
"plugins": [
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
],
|
||||
"sales_channels": [
|
||||
"web",
|
||||
"pretixpos",
|
||||
"resellers"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -404,6 +437,11 @@ Endpoints
|
||||
"plugins": [
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
],
|
||||
"sales_channels": [
|
||||
"web",
|
||||
"pretixpos",
|
||||
"resellers"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -473,6 +511,11 @@ Endpoints
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal",
|
||||
"pretix.plugins.pretixdroid"
|
||||
],
|
||||
"sales_channels": [
|
||||
"web",
|
||||
"pretixpos",
|
||||
"resellers"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,28 @@ expires datetime Expiry date (or
|
||||
conditions string Special terms and conditions for this card (or ``null``)
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
The gift card transaction resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the gift card transaction
|
||||
datetime datetime Creation date of the transaction
|
||||
value money (string) Transaction amount
|
||||
event string Event slug, if the gift card was used in the web shop (or ``null``)
|
||||
order string Order code, if the gift card was used in the web shop (or ``null``)
|
||||
text string Custom text of the transaction (or ``null``)
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. versionadded:: 3.14
|
||||
|
||||
The transaction list endpoint was added.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/giftcards/
|
||||
|
||||
Returns a list of all gift cards issued by a given organizer.
|
||||
@@ -250,3 +269,45 @@ Endpoints
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to change this resource.
|
||||
:statuscode 409: There is not sufficient credit on the gift card.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/giftcards/(id)/transactions/
|
||||
|
||||
List all transactions of a gift card.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/giftcards/1/transactions/ 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": 82,
|
||||
"datetime": "2020-06-22T15:41:42.800534Z",
|
||||
"value": "50.00",
|
||||
"event": "democon",
|
||||
"order": "FXQYW",
|
||||
"text": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to view
|
||||
:param id: The ``id`` field of the gift card to view
|
||||
: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.
|
||||
|
||||
@@ -940,9 +940,9 @@ Creating orders
|
||||
during order generation and is not respected automatically when the order changes later.)
|
||||
|
||||
* ``force`` (optional). If set to ``true``, quotas will be ignored.
|
||||
* ``send_mail`` (optional). If set to ``true``, the same emails will be sent as for a regular order, regardless of
|
||||
* ``send_email`` (optional). If set to ``true``, the same emails will be sent as for a regular order, regardless of
|
||||
whether these emails are enabled for certain sales channels. Defaults to
|
||||
``false``.
|
||||
``false``. Used to be ``send_mail`` before pretix 3.14.
|
||||
|
||||
If you want to use add-on products, you need to set the ``positionid`` fields of all positions manually
|
||||
to incrementing integers starting with ``1``. Then, you can reference one of these
|
||||
@@ -1976,6 +1976,7 @@ Order payment endpoints
|
||||
"amount": "23.00",
|
||||
"payment_date": "2017-12-04T12:13:12Z",
|
||||
"info": {},
|
||||
"send_email": false,
|
||||
"provider": "banktransfer"
|
||||
}
|
||||
|
||||
|
||||
@@ -90,3 +90,120 @@ Endpoints
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
|
||||
|
||||
Organizer settings
|
||||
------------------
|
||||
|
||||
pretix organizers and events have lots and lots of parameters of different types that are stored in a key-value store on our system.
|
||||
Since many of these settings depend on each other in complex ways, we can not give direct access to all of these
|
||||
settings through the API. However, we do expose many of the simple and useful flags through the API.
|
||||
|
||||
Please note that the available settings flags change between pretix versions, and we do not give a guarantee on backwards-compatibility like with other parts of the API.
|
||||
Therefore, we're also not including a list of the options here, but instead recommend to look at the endpoint output
|
||||
to see available options. The ``explain=true`` flag enables a verbose mode that provides you with human-readable
|
||||
information about the properties.
|
||||
|
||||
.. note:: Please note that this is not a complete representation of all organizer settings. You will find more settings
|
||||
in the web interface.
|
||||
|
||||
.. warning:: This API is intended for advanced users. Even though we take care to validate your input, you will be
|
||||
able to break your shops using this API by creating situations of conflicting settings. Please take care.
|
||||
|
||||
.. versionchanged:: 3.14
|
||||
|
||||
Initial support for settings has been added to the API.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/settings/
|
||||
|
||||
Get current values of organizer settings.
|
||||
|
||||
Permission required: "Can change organizer settings"
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/settings/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example standard response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"event_list_type": "calendar",
|
||||
…
|
||||
}
|
||||
|
||||
**Example verbose response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"event_list_type":
|
||||
{
|
||||
"value": "calendar",
|
||||
"label": "Default overview style",
|
||||
"help_text": "If your event series has more than 50 dates in the future, only the month or week calendar can be used."
|
||||
}
|
||||
},
|
||||
…
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to access
|
||||
:query explain: Set to ``true`` to enable verbose response mode
|
||||
: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:patch:: /api/v1/organizers/(organizer)/settings/
|
||||
|
||||
Updates organizer settings. Note that ``PUT`` is not allowed here, only ``PATCH``.
|
||||
|
||||
.. warning::
|
||||
|
||||
Settings can be stored at different levels in pretix. If a value is not set on organizer level, a default setting
|
||||
from a higher level (global) will be returned. If you explicitly set a setting on organizer level, it
|
||||
will no longer be inherited from the higher levels. Therefore, we recommend you to send only settings that you
|
||||
explicitly want to set on organizer level. To unset a settings, pass ``null``.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/settings/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"event_list_type": "calendar"
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"event_list_type": "calendar",
|
||||
…
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to update
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The organizer could not be updated 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.
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
.. spelling:: checkin
|
||||
.. spelling::
|
||||
|
||||
checkin
|
||||
datetime
|
||||
|
||||
.. _rest-questions:
|
||||
|
||||
@@ -53,6 +56,12 @@ options list of objects In case of ques
|
||||
├ identifier string An arbitrary string that can be used for matching with
|
||||
other sources.
|
||||
└ answer multi-lingual string The displayed value of this option
|
||||
valid_number_min string Minimum value for number questions (optional)
|
||||
valid_number_max string Maximum value for number questions (optional)
|
||||
valid_date_min date Minimum value for date questions (optional)
|
||||
valid_date_max date Maximum value for date questions (optional)
|
||||
valid_datetime_min datetime Minimum value for date and time questions (optional)
|
||||
valid_datetime_max datetime Maximum value for date and time 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
|
||||
@@ -92,6 +101,10 @@ dependency_value string An old version
|
||||
|
||||
The attribute ``help_text`` has been added.
|
||||
|
||||
.. versionchanged:: 3.14
|
||||
|
||||
The attributes ``valid_*`` have been added.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
@@ -137,6 +150,12 @@ Endpoints
|
||||
"ask_during_checkin": false,
|
||||
"hidden": false,
|
||||
"print_on_invoice": false,
|
||||
"valid_number_min": null,
|
||||
"valid_number_max": null,
|
||||
"valid_date_min": null,
|
||||
"valid_date_max": null,
|
||||
"valid_datetime_min": null,
|
||||
"valid_datetime_max": null,
|
||||
"dependency_question": null,
|
||||
"dependency_value": null,
|
||||
"dependency_values": [],
|
||||
@@ -208,6 +227,12 @@ Endpoints
|
||||
"ask_during_checkin": false,
|
||||
"hidden": false,
|
||||
"print_on_invoice": false,
|
||||
"valid_number_min": null,
|
||||
"valid_number_max": null,
|
||||
"valid_date_min": null,
|
||||
"valid_date_max": null,
|
||||
"valid_datetime_min": null,
|
||||
"valid_datetime_max": null,
|
||||
"dependency_question": null,
|
||||
"dependency_value": null,
|
||||
"dependency_values": [],
|
||||
@@ -302,6 +327,12 @@ Endpoints
|
||||
"dependency_question": null,
|
||||
"dependency_value": null,
|
||||
"dependency_values": [],
|
||||
"valid_number_min": null,
|
||||
"valid_number_max": null,
|
||||
"valid_date_min": null,
|
||||
"valid_date_max": null,
|
||||
"valid_datetime_min": null,
|
||||
"valid_datetime_max": null,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
@@ -377,6 +408,12 @@ Endpoints
|
||||
"dependency_question": null,
|
||||
"dependency_value": null,
|
||||
"dependency_values": [],
|
||||
"valid_number_min": null,
|
||||
"valid_number_max": null,
|
||||
"valid_date_min": null,
|
||||
"valid_date_max": null,
|
||||
"valid_datetime_min": null,
|
||||
"valid_datetime_max": null,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
|
||||
@@ -7,7 +7,7 @@ localecompile:
|
||||
|
||||
localegen:
|
||||
./manage.py makemessages --keep-pot --ignore "pretix/helpers/*" $(LNGS)
|
||||
./manage.py makemessages --keep-pot -d djangojs --ignore "pretix/helpers/*" --ignore "pretix/static/jsi18n/*" --ignore "pretix/static/jsi18n/*" --ignore "pretix/static.dist/*" --ignore "data/*" --ignore "build/*" $(LNGS)
|
||||
./manage.py makemessages --keep-pot -d djangojs --ignore "pretix/helpers/*" --ignore "pretix/static/jsi18n/*" --ignore "pretix/static/jsi18n/*" --ignore "pretix/static.dist/*" --ignore "data/*" --ignore "pretix/static/rrule/*" --ignore "build/*" $(LNGS)
|
||||
|
||||
staticfiles: jsi18n
|
||||
./manage.py collectstatic --noinput
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "3.13.1"
|
||||
__version__ = "3.14.0.dev0"
|
||||
|
||||
@@ -102,6 +102,7 @@ class PretixPosSecurityProfile(AllowListSecurityProfile):
|
||||
('DELETE', 'api-v1:cartposition-detail'),
|
||||
('GET', 'api-v1:giftcard-list'),
|
||||
('POST', 'api-v1:giftcard-transact'),
|
||||
('GET', 'plugins:pretix_posbackend:posclosing-list'),
|
||||
('POST', 'plugins:pretix_posbackend:posreceipt-list'),
|
||||
('POST', 'plugins:pretix_posbackend:posclosing-list'),
|
||||
('POST', 'plugins:pretix_posbackend:posdebugdump-list'),
|
||||
|
||||
@@ -87,7 +87,10 @@ class CartPositionCreateSerializer(I18nAwareModelSerializer):
|
||||
raise ValidationError('The specified seat ID is not unique.')
|
||||
else:
|
||||
validated_data['seat'] = seat
|
||||
if not seat.is_available(sales_channel=validated_data.get('sales_channel', 'web')):
|
||||
if not seat.is_available(
|
||||
sales_channel=validated_data.get('sales_channel', 'web'),
|
||||
distance_ignore_cart_id=validated_data['cart_id'],
|
||||
):
|
||||
raise ValidationError(gettext_lazy('The selected seat "{seat}" is not available.').format(seat=seat.name))
|
||||
elif seated:
|
||||
raise ValidationError('The specified product requires to choose a seat.')
|
||||
@@ -104,6 +107,7 @@ class CartPositionCreateSerializer(I18nAwareModelSerializer):
|
||||
def validate_cart_id(self, cid):
|
||||
if cid and not cid.endswith('@api'):
|
||||
raise ValidationError('Cart ID should end in @api or be empty.')
|
||||
return cid
|
||||
|
||||
def validate_item(self, item):
|
||||
if item.event != self.context['event']:
|
||||
|
||||
@@ -17,7 +17,7 @@ from pretix.base.models.items import SubEventItem, SubEventItemVariation
|
||||
from pretix.base.services.seating import (
|
||||
SeatProtected, generate_seats, validate_plan_change,
|
||||
)
|
||||
from pretix.base.settings import DEFAULTS, validate_settings
|
||||
from pretix.base.settings import DEFAULTS, validate_event_settings
|
||||
from pretix.base.signals import api_event_settings_fields
|
||||
|
||||
|
||||
@@ -124,7 +124,8 @@ class EventSerializer(I18nAwareModelSerializer):
|
||||
fields = ('name', 'slug', 'live', 'testmode', 'currency', 'date_from',
|
||||
'date_to', 'date_admission', 'is_public', 'presale_start',
|
||||
'presale_end', 'location', 'geo_lat', 'geo_lon', 'has_subevents', 'meta_data', 'seating_plan',
|
||||
'plugins', 'seat_category_mapping', 'timezone', 'item_meta_properties', 'valid_keys')
|
||||
'plugins', 'seat_category_mapping', 'timezone', 'item_meta_properties', 'valid_keys',
|
||||
'sales_channels')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -596,6 +597,7 @@ class EventSettingsSerializer(serializers.Serializer):
|
||||
'attendee_addresses_required',
|
||||
'attendee_company_asked',
|
||||
'attendee_company_required',
|
||||
'attendee_data_explanation_text',
|
||||
'confirm_texts',
|
||||
'order_email_asked_twice',
|
||||
'payment_term_mode',
|
||||
@@ -606,6 +608,7 @@ class EventSettingsSerializer(serializers.Serializer):
|
||||
'payment_term_expire_automatically',
|
||||
'payment_term_accept_late',
|
||||
'payment_explanation',
|
||||
'payment_pending_hidden',
|
||||
'ticket_download',
|
||||
'ticket_download_date',
|
||||
'ticket_download_addons',
|
||||
@@ -661,10 +664,17 @@ class EventSettingsSerializer(serializers.Serializer):
|
||||
'change_allow_user_variation',
|
||||
'change_allow_user_until',
|
||||
'change_allow_user_price',
|
||||
'primary_color',
|
||||
'theme_color_success',
|
||||
'theme_color_danger',
|
||||
'theme_color_background',
|
||||
'theme_round_borders',
|
||||
'primary_font',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.event = kwargs.pop('event')
|
||||
self.changed_data = []
|
||||
super().__init__(*args, **kwargs)
|
||||
for fname in self.default_fields:
|
||||
kwargs = DEFAULTS[fname].get('serializer_kwargs', {})
|
||||
@@ -693,15 +703,17 @@ class EventSettingsSerializer(serializers.Serializer):
|
||||
for attr, value in validated_data.items():
|
||||
if value is None:
|
||||
instance.delete(attr)
|
||||
self.changed_data.append(attr)
|
||||
elif instance.get(attr, as_type=type(value)) != value:
|
||||
instance.set(attr, value)
|
||||
self.changed_data.append(attr)
|
||||
return instance
|
||||
|
||||
def validate(self, data):
|
||||
data = super().validate(data)
|
||||
settings_dict = self.instance.freeze()
|
||||
settings_dict.update(data)
|
||||
validate_settings(self.event, settings_dict)
|
||||
validate_event_settings(self.event, settings_dict)
|
||||
return data
|
||||
|
||||
|
||||
|
||||
@@ -277,7 +277,9 @@ class QuestionSerializer(I18nAwareModelSerializer):
|
||||
model = Question
|
||||
fields = ('id', 'question', 'type', 'required', 'items', 'options', 'position',
|
||||
'ask_during_checkin', 'identifier', 'dependency_question', 'dependency_values',
|
||||
'hidden', 'dependency_value', 'print_on_invoice', 'help_text')
|
||||
'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'
|
||||
)
|
||||
|
||||
def validate_identifier(self, value):
|
||||
Question._clean_identifier(self.context['event'], value, self.instance)
|
||||
|
||||
@@ -682,7 +682,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
consume_carts = serializers.ListField(child=serializers.CharField(), required=False)
|
||||
force = serializers.BooleanField(default=False, required=False)
|
||||
payment_date = serializers.DateTimeField(required=False, allow_null=True)
|
||||
send_mail = serializers.BooleanField(default=False, required=False)
|
||||
send_email = serializers.BooleanField(default=False, required=False)
|
||||
simulate = serializers.BooleanField(default=False, required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -693,7 +693,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
model = Order
|
||||
fields = ('code', 'status', 'testmode', 'email', 'locale', 'payment_provider', 'fees', 'comment', 'sales_channel',
|
||||
'invoice_address', 'positions', 'checkin_attention', 'payment_info', 'payment_date', 'consume_carts',
|
||||
'force', 'send_mail', 'simulate')
|
||||
'force', 'send_email', 'simulate')
|
||||
|
||||
def validate_payment_provider(self, pp):
|
||||
if pp is None:
|
||||
@@ -786,7 +786,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
payment_date = validated_data.pop('payment_date', now())
|
||||
force = validated_data.pop('force', False)
|
||||
simulate = validated_data.pop('simulate', False)
|
||||
self._send_mail = validated_data.pop('send_mail', False)
|
||||
self._send_mail = validated_data.pop('send_email', False)
|
||||
|
||||
if 'invoice_address' in validated_data:
|
||||
iadata = validated_data.pop('invoice_address')
|
||||
|
||||
@@ -2,6 +2,7 @@ from decimal import Decimal
|
||||
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import get_language, gettext_lazy as _
|
||||
from hierarkey.proxy import HierarkeyProxy
|
||||
from rest_framework import serializers
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
@@ -9,11 +10,12 @@ from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
||||
from pretix.api.serializers.order import CompatibleJSONField
|
||||
from pretix.base.auth import get_auth_backends
|
||||
from pretix.base.models import (
|
||||
Device, GiftCard, Organizer, SeatingPlan, Team, TeamAPIToken, TeamInvite,
|
||||
User,
|
||||
Device, GiftCard, GiftCardTransaction, Organizer, SeatingPlan, Team,
|
||||
TeamAPIToken, TeamInvite, User,
|
||||
)
|
||||
from pretix.base.models.seating import SeatingPlanLayoutValidator
|
||||
from pretix.base.services.mail import SendMailException, mail
|
||||
from pretix.base.settings import DEFAULTS, validate_organizer_settings
|
||||
from pretix.helpers.urls import build_absolute_uri
|
||||
|
||||
|
||||
@@ -59,6 +61,21 @@ class GiftCardSerializer(I18nAwareModelSerializer):
|
||||
fields = ('id', 'secret', 'issuance', 'value', 'currency', 'testmode', 'expires', 'conditions')
|
||||
|
||||
|
||||
class OrderEventSlugField(serializers.RelatedField):
|
||||
|
||||
def to_representation(self, obj):
|
||||
return obj.event.slug
|
||||
|
||||
|
||||
class GiftCardTransactionSerializer(I18nAwareModelSerializer):
|
||||
order = serializers.SlugRelatedField(slug_field='code', read_only=True)
|
||||
event = OrderEventSlugField(source='order', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = GiftCardTransaction
|
||||
fields = ('id', 'datetime', 'value', 'event', 'order', 'text')
|
||||
|
||||
|
||||
class EventSlugField(serializers.SlugRelatedField):
|
||||
def get_queryset(self):
|
||||
return self.context['organizer'].events.all()
|
||||
@@ -187,3 +204,63 @@ class TeamMemberSerializer(serializers.ModelSerializer):
|
||||
fields = (
|
||||
'id', 'email', 'fullname', 'require_2fa'
|
||||
)
|
||||
|
||||
|
||||
class OrganizerSettingsSerializer(serializers.Serializer):
|
||||
default_fields = [
|
||||
'organizer_info_text',
|
||||
'event_list_type',
|
||||
'event_list_availability',
|
||||
'organizer_homepage_text',
|
||||
'organizer_link_back',
|
||||
'organizer_logo_image_large',
|
||||
'giftcard_length',
|
||||
'giftcard_expiry_years',
|
||||
'locales',
|
||||
'event_team_provisioning',
|
||||
'primary_color',
|
||||
'theme_color_success',
|
||||
'theme_color_danger',
|
||||
'theme_color_background',
|
||||
'theme_round_borders',
|
||||
'primary_font'
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.organizer = kwargs.pop('organizer')
|
||||
self.changed_data = []
|
||||
super().__init__(*args, **kwargs)
|
||||
for fname in self.default_fields:
|
||||
kwargs = DEFAULTS[fname].get('serializer_kwargs', {})
|
||||
if callable(kwargs):
|
||||
kwargs = kwargs()
|
||||
kwargs.setdefault('required', False)
|
||||
kwargs.setdefault('allow_null', True)
|
||||
form_kwargs = DEFAULTS[fname].get('form_kwargs', {})
|
||||
if callable(form_kwargs):
|
||||
form_kwargs = form_kwargs()
|
||||
if 'serializer_class' not in DEFAULTS[fname]:
|
||||
raise ValidationError('{} has no serializer class'.format(fname))
|
||||
f = DEFAULTS[fname]['serializer_class'](
|
||||
**kwargs
|
||||
)
|
||||
f._label = form_kwargs.get('label', fname)
|
||||
f._help_text = form_kwargs.get('help_text')
|
||||
self.fields[fname] = f
|
||||
|
||||
def update(self, instance: HierarkeyProxy, validated_data):
|
||||
for attr, value in validated_data.items():
|
||||
if value is None:
|
||||
instance.delete(attr)
|
||||
self.changed_data.append(attr)
|
||||
elif instance.get(attr, as_type=type(value)) != value:
|
||||
instance.set(attr, value)
|
||||
self.changed_data.append(attr)
|
||||
return instance
|
||||
|
||||
def validate(self, data):
|
||||
data = super().validate(data)
|
||||
settings_dict = self.instance.freeze()
|
||||
settings_dict.update(data)
|
||||
validate_organizer_settings(self.organizer, settings_dict)
|
||||
return data
|
||||
|
||||
@@ -62,6 +62,9 @@ order_router = routers.DefaultRouter()
|
||||
order_router.register(r'payments', order.PaymentViewSet)
|
||||
order_router.register(r'refunds', order.RefundViewSet)
|
||||
|
||||
giftcard_router = routers.DefaultRouter()
|
||||
giftcard_router.register(r'transactions', organizer.GiftCardTransactionViewSet)
|
||||
|
||||
# Force import of all plugins to give them a chance to register URLs with the router
|
||||
for app in apps.get_app_configs():
|
||||
if hasattr(app, 'PretixPluginMeta'):
|
||||
@@ -71,6 +74,9 @@ for app in apps.get_app_configs():
|
||||
urlpatterns = [
|
||||
url(r'^', include(router.urls)),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/', include(orga_router.urls)),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/settings/$', organizer.OrganizerSettingsView.as_view(),
|
||||
name="organizer.settings"),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/giftcards/(?P<giftcard>[^/]+)/', include(giftcard_router.urls)),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/settings/$', event.EventSettingsView.as_view(),
|
||||
name="event.settings"),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/', include(event_router.urls)),
|
||||
|
||||
@@ -131,7 +131,7 @@ class EventSelectionView(APIView):
|
||||
|
||||
@property
|
||||
def base_event_qs(self):
|
||||
qs = self.request.auth.organizer.events.annotate(
|
||||
qs = self.request.auth.get_events_with_any_permission().annotate(
|
||||
first_date=Coalesce('date_admission', 'date_from'),
|
||||
last_date=Coalesce('date_to', 'date_from'),
|
||||
).filter(
|
||||
@@ -154,6 +154,7 @@ class EventSelectionView(APIView):
|
||||
).filter(
|
||||
event__organizer=self.request.auth.organizer,
|
||||
event__live=True,
|
||||
event__in=self.request.auth.get_events_with_any_permission(),
|
||||
active=True,
|
||||
).select_related('event').order_by('first_date')
|
||||
if self.request.auth.gate:
|
||||
|
||||
@@ -18,7 +18,9 @@ from pretix.base.models import (
|
||||
CartPosition, Device, Event, TaxRule, TeamAPIToken,
|
||||
)
|
||||
from pretix.base.models.event import SubEvent
|
||||
from pretix.base.settings import SETTINGS_AFFECTING_CSS
|
||||
from pretix.helpers.dicts import merge_dicts
|
||||
from pretix.presale.style import regenerate_css
|
||||
from pretix.presale.views.organizer import filter_qs_by_attr
|
||||
|
||||
with scopes_disabled():
|
||||
@@ -26,6 +28,7 @@ with scopes_disabled():
|
||||
is_past = django_filters.rest_framework.BooleanFilter(method='is_past_qs')
|
||||
is_future = django_filters.rest_framework.BooleanFilter(method='is_future_qs')
|
||||
ends_after = django_filters.rest_framework.IsoDateTimeFilter(method='ends_after_qs')
|
||||
sales_channel = django_filters.rest_framework.CharFilter(method='sales_channel_qs')
|
||||
|
||||
class Meta:
|
||||
model = Event
|
||||
@@ -67,6 +70,9 @@ with scopes_disabled():
|
||||
else:
|
||||
return queryset.exclude(expr)
|
||||
|
||||
def sales_channel_qs(self, queryset, name, value):
|
||||
return queryset.filter(sales_channels__contains=value)
|
||||
|
||||
|
||||
class EventViewSet(viewsets.ModelViewSet):
|
||||
serializer_class = EventSerializer
|
||||
@@ -385,5 +391,7 @@ class EventSettingsView(views.APIView):
|
||||
k: v for k, v in s.validated_data.items()
|
||||
}
|
||||
)
|
||||
if any(p in s.changed_data for p in SETTINGS_AFFECTING_CSS):
|
||||
regenerate_css.apply_async(args=(request.organizer.pk,))
|
||||
s = EventSettingsSerializer(instance=request.event.settings, event=request.event)
|
||||
return Response(s.data)
|
||||
|
||||
@@ -81,9 +81,9 @@ class ExportersMixin:
|
||||
serializer = JobRunSerializer(exporter=instance, data=self.request.data, **self.get_serializer_kwargs())
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
cf = CachedFile(web_download=False)
|
||||
cf = CachedFile()
|
||||
cf.date = now()
|
||||
cf.expires = now() + timedelta(hours=24)
|
||||
cf.expires = now() + timedelta(days=3)
|
||||
cf.save()
|
||||
d = serializer.data
|
||||
for k, v in d.items():
|
||||
|
||||
@@ -558,6 +558,8 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
if 'send_mail' in request.data and 'send_email' not in request.data:
|
||||
request.data['send_email'] = request.data['send_mail']
|
||||
serializer = OrderCreateSerializer(data=request.data, context=self.get_serializer_context())
|
||||
serializer.is_valid(raise_exception=True)
|
||||
with transaction.atomic():
|
||||
@@ -949,6 +951,7 @@ class PaymentViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
|
||||
def get_serializer_context(self):
|
||||
ctx = super().get_serializer_context()
|
||||
ctx['order'] = get_object_or_404(Order, code=self.kwargs['order'], event=self.request.event)
|
||||
ctx['event'] = self.request.event
|
||||
return ctx
|
||||
|
||||
def get_queryset(self):
|
||||
@@ -956,6 +959,7 @@ class PaymentViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
|
||||
return order.payments.all()
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
send_mail = request.data.get('send_email', True)
|
||||
serializer = OrderPaymentCreateSerializer(data=request.data, context=self.get_serializer_context())
|
||||
serializer.is_valid(raise_exception=True)
|
||||
with transaction.atomic():
|
||||
@@ -971,7 +975,8 @@ class PaymentViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
|
||||
user=self.request.user if self.request.user.is_authenticated else None,
|
||||
auth=self.request.auth,
|
||||
count_waitinglist=False,
|
||||
force=request.data.get('force', False)
|
||||
force=request.data.get('force', False),
|
||||
send_mail=send_mail,
|
||||
)
|
||||
except Quota.QuotaExceededException:
|
||||
pass
|
||||
|
||||
@@ -6,7 +6,9 @@ from django.shortcuts import get_object_or_404
|
||||
from django.utils.functional import cached_property
|
||||
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
|
||||
from django_scopes import scopes_disabled
|
||||
from rest_framework import filters, mixins, serializers, status, viewsets
|
||||
from rest_framework import (
|
||||
filters, mixins, serializers, status, views, viewsets,
|
||||
)
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import MethodNotAllowed, PermissionDenied
|
||||
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin
|
||||
@@ -15,15 +17,18 @@ from rest_framework.viewsets import GenericViewSet
|
||||
|
||||
from pretix.api.models import OAuthAccessToken
|
||||
from pretix.api.serializers.organizer import (
|
||||
DeviceSerializer, GiftCardSerializer, OrganizerSerializer,
|
||||
SeatingPlanSerializer, TeamAPITokenSerializer, TeamInviteSerializer,
|
||||
TeamMemberSerializer, TeamSerializer,
|
||||
DeviceSerializer, GiftCardSerializer, GiftCardTransactionSerializer,
|
||||
OrganizerSerializer, OrganizerSettingsSerializer, SeatingPlanSerializer,
|
||||
TeamAPITokenSerializer, TeamInviteSerializer, TeamMemberSerializer,
|
||||
TeamSerializer,
|
||||
)
|
||||
from pretix.base.models import (
|
||||
Device, GiftCard, Organizer, SeatingPlan, Team, TeamAPIToken, TeamInvite,
|
||||
User,
|
||||
Device, GiftCard, GiftCardTransaction, Organizer, SeatingPlan, Team,
|
||||
TeamAPIToken, TeamInvite, User,
|
||||
)
|
||||
from pretix.base.settings import SETTINGS_AFFECTING_CSS
|
||||
from pretix.helpers.dicts import merge_dicts
|
||||
from pretix.presale.style import regenerate_organizer_css
|
||||
|
||||
|
||||
class OrganizerViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
@@ -191,6 +196,24 @@ class GiftCardViewSet(viewsets.ModelViewSet):
|
||||
raise MethodNotAllowed("Gift cards cannot be deleted.")
|
||||
|
||||
|
||||
class GiftCardTransactionViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
serializer_class = GiftCardTransactionSerializer
|
||||
queryset = GiftCardTransaction.objects.none()
|
||||
permission = 'can_manage_gift_cards'
|
||||
write_permission = 'can_manage_gift_cards'
|
||||
|
||||
@cached_property
|
||||
def giftcard(self):
|
||||
if self.request.GET.get('include_accepted') == 'true':
|
||||
qs = self.request.organizer.accepted_gift_cards
|
||||
else:
|
||||
qs = self.request.organizer.issued_gift_cards.all()
|
||||
return get_object_or_404(qs, pk=self.kwargs.get('giftcard'))
|
||||
|
||||
def get_queryset(self):
|
||||
return self.giftcard.transactions.select_related('order', 'order__event')
|
||||
|
||||
|
||||
class TeamViewSet(viewsets.ModelViewSet):
|
||||
serializer_class = TeamSerializer
|
||||
queryset = Team.objects.none()
|
||||
@@ -396,3 +419,37 @@ class DeviceViewSet(mixins.CreateModelMixin,
|
||||
data=self.request.data
|
||||
)
|
||||
return inst
|
||||
|
||||
|
||||
class OrganizerSettingsView(views.APIView):
|
||||
permission = 'can_change_organizer_settings'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
s = OrganizerSettingsSerializer(instance=request.organizer.settings, organizer=request.organizer)
|
||||
if 'explain' in request.GET:
|
||||
return Response({
|
||||
fname: {
|
||||
'value': s.data[fname],
|
||||
'label': getattr(field, '_label', fname),
|
||||
'help_text': getattr(field, '_help_text', None)
|
||||
} for fname, field in s.fields.items()
|
||||
})
|
||||
return Response(s.data)
|
||||
|
||||
def patch(self, request, *wargs, **kwargs):
|
||||
s = OrganizerSettingsSerializer(
|
||||
instance=request.organizer.settings, data=request.data, partial=True,
|
||||
organizer=request.organizer
|
||||
)
|
||||
s.is_valid(raise_exception=True)
|
||||
with transaction.atomic():
|
||||
s.save()
|
||||
self.request.organizer.log_action(
|
||||
'pretix.organizer.settings', user=self.request.user, auth=self.request.auth, data={
|
||||
k: v for k, v in s.validated_data.items()
|
||||
}
|
||||
)
|
||||
if any(p in s.changed_data for p in SETTINGS_AFFECTING_CSS):
|
||||
regenerate_organizer_css.apply_async(args=(request.organizer.pk,))
|
||||
s = OrganizerSettingsSerializer(instance=request.organizer.settings, organizer=request.organizer)
|
||||
return Response(s.data)
|
||||
|
||||
@@ -4,3 +4,4 @@ from .invoices import * # noqa
|
||||
from .json import * # noqa
|
||||
from .mail import * # noqa
|
||||
from .orderlist import * # noqa
|
||||
from .waitinglist import * # noqa
|
||||
|
||||
@@ -147,8 +147,8 @@ class OrderListExporter(MultiSheetListExporter):
|
||||
for k, label, w in name_scheme['fields']:
|
||||
headers.append(label)
|
||||
headers += [
|
||||
_('Address'), _('ZIP code'), _('City'), _('Country'), pgettext('address', 'State'), _('VAT ID'),
|
||||
_('Date of last payment'), _('Fees'), _('Order locale')
|
||||
_('Address'), _('ZIP code'), _('City'), _('Country'), pgettext('address', 'State'),
|
||||
_('Custom address field'), _('VAT ID'), _('Date of last payment'), _('Fees'), _('Order locale')
|
||||
]
|
||||
|
||||
for tr in tax_rates:
|
||||
@@ -235,10 +235,11 @@ class OrderListExporter(MultiSheetListExporter):
|
||||
order.invoice_address.country if order.invoice_address.country else
|
||||
order.invoice_address.country_old,
|
||||
order.invoice_address.state,
|
||||
order.invoice_address.custom_field,
|
||||
order.invoice_address.vat_id,
|
||||
]
|
||||
except InvoiceAddress.DoesNotExist:
|
||||
row += [''] * (8 + (len(name_scheme['fields']) if name_scheme and len(name_scheme['fields']) > 1 else 0))
|
||||
row += [''] * (9 + (len(name_scheme['fields']) if name_scheme and len(name_scheme['fields']) > 1 else 0))
|
||||
|
||||
row += [
|
||||
order.payment_date.astimezone(tz).strftime('%Y-%m-%d') if order.payment_date else '',
|
||||
|
||||
165
src/pretix/base/exporters/waitinglist.py
Normal file
165
src/pretix/base/exporters/waitinglist.py
Normal file
@@ -0,0 +1,165 @@
|
||||
from collections import OrderedDict
|
||||
|
||||
import pytz
|
||||
from django import forms
|
||||
from django.db.models import F, Q
|
||||
from django.dispatch import receiver
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
|
||||
from pretix.base.models.waitinglist import WaitingListEntry
|
||||
|
||||
from ..exporter import ListExporter
|
||||
from ..signals import (
|
||||
register_data_exporters, register_multievent_data_exporters,
|
||||
)
|
||||
|
||||
|
||||
class WaitingListExporter(ListExporter):
|
||||
identifier = 'waitinglist'
|
||||
verbose_name = _('Waiting list')
|
||||
|
||||
# map selected status to label and queryset-filter
|
||||
status_filters = [
|
||||
(
|
||||
'',
|
||||
_('All entries'),
|
||||
lambda qs: qs
|
||||
),
|
||||
(
|
||||
'awaiting-voucher',
|
||||
_('Waiting for a voucher'),
|
||||
lambda qs: qs.filter(voucher__isnull=True)
|
||||
),
|
||||
(
|
||||
'voucher-assigned',
|
||||
_('Voucher assigned'),
|
||||
lambda qs: qs.filter(voucher__isnull=False)
|
||||
),
|
||||
(
|
||||
'awaiting-redemption',
|
||||
_('Waiting for redemption'),
|
||||
lambda qs: qs.filter(
|
||||
voucher__isnull=False,
|
||||
voucher__redeemed__lt=F('voucher__max_usages'),
|
||||
).filter(Q(voucher__valid_until__isnull=True) | Q(voucher__valid_until__gt=now()))
|
||||
),
|
||||
(
|
||||
'voucher-redeemed',
|
||||
_('Voucher redeemed'),
|
||||
lambda qs: qs.filter(
|
||||
voucher__isnull=False,
|
||||
voucher__redeemed__gte=F('voucher__max_usages'),
|
||||
)
|
||||
),
|
||||
(
|
||||
'voucher-expired',
|
||||
_('Voucher expired'),
|
||||
lambda qs: qs.filter(
|
||||
voucher__isnull=False,
|
||||
voucher__redeemed__lt=F('voucher__max_usages'),
|
||||
voucher__valid_until__isnull=False,
|
||||
voucher__valid_until__lte=now()
|
||||
)
|
||||
),
|
||||
]
|
||||
|
||||
def iterate_list(self, form_data):
|
||||
# create dicts for easier access by key, which is passed by form_data[status]
|
||||
status_labels = {k: v for k, v, c in self.status_filters}
|
||||
queryset_mutators = {k: c for k, v, c in self.status_filters}
|
||||
|
||||
entries = WaitingListEntry.objects.filter(
|
||||
event__in=self.events,
|
||||
).select_related(
|
||||
'item', 'variation', 'voucher', 'subevent'
|
||||
).order_by('created')
|
||||
|
||||
# apply filter to queryset/entries according to status
|
||||
# if unknown status-filter is given, django will handle the error
|
||||
status_filter = form_data.get("status", "")
|
||||
entries = queryset_mutators[status_filter](entries)
|
||||
|
||||
headers = [
|
||||
_('Date'),
|
||||
_('Email'),
|
||||
_('Product name'),
|
||||
_('Variation'),
|
||||
_('Event slug'),
|
||||
_('Event name'),
|
||||
pgettext_lazy('subevents', 'Date'), # Name of subevent
|
||||
_('Start date'), # Start date of subevent or event
|
||||
_('End date'), # End date of subevent or event
|
||||
_('Language'),
|
||||
_('Priority'),
|
||||
_('Status'),
|
||||
_('Voucher code'),
|
||||
]
|
||||
|
||||
yield headers
|
||||
yield self.ProgressSetTotal(total=len(entries))
|
||||
|
||||
for entry in entries:
|
||||
if entry.voucher:
|
||||
if entry.voucher.redeemed >= entry.voucher.max_usages:
|
||||
status_label = status_labels['voucher-redeemed']
|
||||
elif not entry.voucher.is_active():
|
||||
status_label = status_labels['voucher-expired']
|
||||
else:
|
||||
status_label = status_labels['voucher-assigned']
|
||||
else:
|
||||
status_label = status_labels['awaiting-voucher']
|
||||
|
||||
# which event should be used to output dates in columns "Start date" and "End date"
|
||||
event_for_date_columns = entry.subevent if entry.subevent else entry.event
|
||||
tz = pytz.timezone(entry.event.settings.timezone)
|
||||
datetime_format = '%Y-%m-%d %H:%M:%S'
|
||||
|
||||
row = [
|
||||
entry.created.astimezone(tz).strftime(datetime_format), # alternative: .isoformat(),
|
||||
entry.email,
|
||||
str(entry.item) if entry.item else "",
|
||||
str(entry.variation) if entry.variation else "",
|
||||
entry.event.slug,
|
||||
entry.event.name,
|
||||
entry.subevent.name if entry.subevent else "",
|
||||
event_for_date_columns.date_from.astimezone(tz).strftime(datetime_format),
|
||||
event_for_date_columns.date_to.astimezone(tz).strftime(datetime_format) if event_for_date_columns.date_to else "",
|
||||
entry.locale,
|
||||
str(entry.priority),
|
||||
status_label,
|
||||
entry.voucher.code if entry.voucher else '',
|
||||
]
|
||||
yield row
|
||||
|
||||
@property
|
||||
def additional_form_fields(self):
|
||||
return OrderedDict(
|
||||
[
|
||||
('status',
|
||||
forms.ChoiceField(
|
||||
label=_('Status'),
|
||||
initial=['awaiting-voucher'],
|
||||
required=False,
|
||||
choices=[(k, v) for (k, v, c) in self.status_filters]
|
||||
)),
|
||||
]
|
||||
)
|
||||
|
||||
def get_filename(self):
|
||||
if self.is_multievent:
|
||||
event = self.events.first()
|
||||
slug = event.organizer.slug if len(self.events) > 1 else event.slug
|
||||
else:
|
||||
slug = self.event.slug
|
||||
return '{}_waitinglist'.format(slug)
|
||||
|
||||
|
||||
@receiver(register_data_exporters, dispatch_uid="exporter_waitinglist")
|
||||
def register_waitinglist_exporter(sender, **kwargs):
|
||||
return WaitingListExporter
|
||||
|
||||
|
||||
@receiver(register_multievent_data_exporters, dispatch_uid="multiexporter_waitinglist")
|
||||
def register_multievent_i_waitinglist_exporter(sender, **kwargs):
|
||||
return WaitingListExporter
|
||||
@@ -1,17 +1,12 @@
|
||||
import hashlib
|
||||
import ipaddress
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.password_validation import (
|
||||
password_validators_help_texts, validate_password,
|
||||
)
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from pretix.base.models import User
|
||||
from pretix.helpers.dicts import move_to_end
|
||||
from pretix.helpers.http import get_client_ip
|
||||
|
||||
|
||||
class LoginForm(forms.Form):
|
||||
@@ -23,7 +18,6 @@ class LoginForm(forms.Form):
|
||||
|
||||
error_messages = {
|
||||
'invalid_login': _("This combination of credentials is not known to our system."),
|
||||
'rate_limit': _("For security reasons, please wait 5 minutes before you try again."),
|
||||
'inactive': _("This account is inactive.")
|
||||
}
|
||||
|
||||
@@ -45,36 +39,10 @@ class LoginForm(forms.Form):
|
||||
else:
|
||||
move_to_end(self.fields, 'keep_logged_in')
|
||||
|
||||
@cached_property
|
||||
def ratelimit_key(self):
|
||||
if not settings.HAS_REDIS:
|
||||
return None
|
||||
client_ip = get_client_ip(self.request)
|
||||
if not client_ip:
|
||||
return None
|
||||
try:
|
||||
client_ip = ipaddress.ip_address(client_ip)
|
||||
except ValueError:
|
||||
# Web server not set up correctly
|
||||
return None
|
||||
if client_ip.is_private:
|
||||
# This is the private IP of the server, web server not set up correctly
|
||||
return None
|
||||
return 'pretix_login_{}'.format(hashlib.sha1(str(client_ip).encode()).hexdigest())
|
||||
|
||||
def clean(self):
|
||||
if all(k in self.cleaned_data for k, f in self.fields.items() if f.required):
|
||||
if self.ratelimit_key:
|
||||
from django_redis import get_redis_connection
|
||||
rc = get_redis_connection("redis")
|
||||
cnt = rc.get(self.ratelimit_key)
|
||||
if cnt and int(cnt) > 10:
|
||||
raise forms.ValidationError(self.error_messages['rate_limit'], code='rate_limit')
|
||||
self.user_cache = self.backend.form_authenticate(self.request, self.cleaned_data)
|
||||
if self.user_cache is None:
|
||||
if self.ratelimit_key:
|
||||
rc.incr(self.ratelimit_key)
|
||||
rc.expire(self.ratelimit_key, 300)
|
||||
raise forms.ValidationError(
|
||||
self.error_messages['invalid_login'],
|
||||
code='invalid_login'
|
||||
|
||||
@@ -13,10 +13,13 @@ from babel import localedata
|
||||
from django import forms
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db.models import QuerySet
|
||||
from django.forms import Select
|
||||
from django.utils.formats import date_format
|
||||
from django.utils.html import escape
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.timezone import get_current_timezone
|
||||
from django.utils.translation import (
|
||||
get_language, gettext_lazy as _, pgettext_lazy,
|
||||
)
|
||||
@@ -234,6 +237,43 @@ class QuestionCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
|
||||
option_template_name = 'pretixbase/forms/widgets/checkbox_option_with_links.html'
|
||||
|
||||
|
||||
class MinDateValidator(MinValueValidator):
|
||||
def __call__(self, value):
|
||||
try:
|
||||
return super().__call__(value)
|
||||
except ValidationError as e:
|
||||
e.params['limit_value'] = date_format(e.params['limit_value'], 'SHORT_DATE_FORMAT')
|
||||
raise e
|
||||
|
||||
|
||||
class MinDateTimeValidator(MinValueValidator):
|
||||
def __call__(self, value):
|
||||
try:
|
||||
return super().__call__(value)
|
||||
except ValidationError as e:
|
||||
e.params['limit_value'] = date_format(e.params['limit_value'].astimezone(get_current_timezone()), 'SHORT_DATETIME_FORMAT')
|
||||
raise e
|
||||
|
||||
|
||||
class MaxDateValidator(MaxValueValidator):
|
||||
|
||||
def __call__(self, value):
|
||||
try:
|
||||
return super().__call__(value)
|
||||
except ValidationError as e:
|
||||
e.params['limit_value'] = date_format(e.params['limit_value'], 'SHORT_DATE_FORMAT')
|
||||
raise e
|
||||
|
||||
|
||||
class MaxDateTimeValidator(MaxValueValidator):
|
||||
def __call__(self, value):
|
||||
try:
|
||||
return super().__call__(value)
|
||||
except ValidationError as e:
|
||||
e.params['limit_value'] = date_format(e.params['limit_value'].astimezone(get_current_timezone()), 'SHORT_DATETIME_FORMAT')
|
||||
raise e
|
||||
|
||||
|
||||
class BaseQuestionsForm(forms.Form):
|
||||
"""
|
||||
This form class is responsible for asking order-related questions. This includes
|
||||
@@ -392,9 +432,10 @@ class BaseQuestionsForm(forms.Form):
|
||||
elif q.type == Question.TYPE_NUMBER:
|
||||
field = forms.DecimalField(
|
||||
label=label, required=required,
|
||||
min_value=q.valid_number_min or Decimal('0.00'),
|
||||
max_value=q.valid_number_max,
|
||||
help_text=q.help_text,
|
||||
initial=initial.answer if initial else None,
|
||||
min_value=Decimal('0.00'),
|
||||
)
|
||||
elif q.type == Question.TYPE_STRING:
|
||||
field = forms.CharField(
|
||||
@@ -453,12 +494,21 @@ class BaseQuestionsForm(forms.Form):
|
||||
max_size=10 * 1024 * 1024,
|
||||
)
|
||||
elif q.type == Question.TYPE_DATE:
|
||||
attrs = {}
|
||||
if q.valid_date_min:
|
||||
attrs['data-min'] = q.valid_date_min.isoformat()
|
||||
if q.valid_date_max:
|
||||
attrs['data-max'] = q.valid_date_max.isoformat()
|
||||
field = forms.DateField(
|
||||
label=label, required=required,
|
||||
help_text=help_text,
|
||||
initial=dateutil.parser.parse(initial.answer).date() if initial and initial.answer else None,
|
||||
widget=DatePickerWidget(),
|
||||
widget=DatePickerWidget(attrs),
|
||||
)
|
||||
if q.valid_date_min:
|
||||
field.validators.append(MinDateValidator(q.valid_date_min))
|
||||
if q.valid_date_max:
|
||||
field.validators.append(MaxDateValidator(q.valid_date_max))
|
||||
elif q.type == Question.TYPE_TIME:
|
||||
field = forms.TimeField(
|
||||
label=label, required=required,
|
||||
@@ -471,8 +521,16 @@ class BaseQuestionsForm(forms.Form):
|
||||
label=label, required=required,
|
||||
help_text=help_text,
|
||||
initial=dateutil.parser.parse(initial.answer).astimezone(tz) if initial and initial.answer else None,
|
||||
widget=SplitDateTimePickerWidget(time_format=get_format_without_seconds('TIME_INPUT_FORMATS')),
|
||||
widget=SplitDateTimePickerWidget(
|
||||
time_format=get_format_without_seconds('TIME_INPUT_FORMATS'),
|
||||
min_date=q.valid_datetime_min,
|
||||
max_date=q.valid_datetime_max
|
||||
),
|
||||
)
|
||||
if q.valid_datetime_min:
|
||||
field.validators.append(MinDateTimeValidator(q.valid_datetime_min))
|
||||
if q.valid_datetime_max:
|
||||
field.validators.append(MaxDateTimeValidator(q.valid_datetime_max))
|
||||
elif q.type == Question.TYPE_PHONENUMBER:
|
||||
babel_locale = 'en'
|
||||
# Babel, and therefore django-phonenumberfield, do not support our custom locales such das de_Informal
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.hashers import check_password
|
||||
from django.contrib.auth.password_validation import (
|
||||
password_validators_help_texts, validate_password,
|
||||
@@ -20,7 +19,6 @@ class UserSettingsForm(forms.ModelForm):
|
||||
"address or password."),
|
||||
'pw_current_wrong': _("The current password you entered was not correct."),
|
||||
'pw_mismatch': _("Please enter the same password twice"),
|
||||
'rate_limit': _("For security reasons, please wait 5 minutes before you try again."),
|
||||
}
|
||||
|
||||
old_pw = forms.CharField(max_length=255,
|
||||
@@ -66,18 +64,6 @@ class UserSettingsForm(forms.ModelForm):
|
||||
|
||||
def clean_old_pw(self):
|
||||
old_pw = self.cleaned_data.get('old_pw')
|
||||
|
||||
if old_pw and settings.HAS_REDIS:
|
||||
from django_redis import get_redis_connection
|
||||
rc = get_redis_connection("redis")
|
||||
cnt = rc.incr('pretix_pwchange_%s' % self.user.pk)
|
||||
rc.expire('pretix_pwchange_%s' % self.user.pk, 300)
|
||||
if cnt > 10:
|
||||
raise forms.ValidationError(
|
||||
self.error_messages['rate_limit'],
|
||||
code='rate_limit',
|
||||
)
|
||||
|
||||
if old_pw and not check_password(old_pw, self.user.password):
|
||||
raise forms.ValidationError(
|
||||
self.error_messages['pw_current_wrong'],
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import os
|
||||
from datetime import date
|
||||
|
||||
from django import forms
|
||||
from django.utils.formats import get_format
|
||||
from django.utils.functional import lazy
|
||||
from django.utils.timezone import now
|
||||
from django.utils.timezone import get_current_timezone, now
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
@@ -92,7 +93,7 @@ class UploadedFileWidget(forms.ClearableFileInput):
|
||||
class SplitDateTimePickerWidget(forms.SplitDateTimeWidget):
|
||||
template_name = 'pretixbase/forms/widgets/splitdatetime.html'
|
||||
|
||||
def __init__(self, attrs=None, date_format=None, time_format=None):
|
||||
def __init__(self, attrs=None, date_format=None, time_format=None, min_date=None, max_date=None):
|
||||
attrs = attrs or {}
|
||||
if 'placeholder' in attrs:
|
||||
del attrs['placeholder']
|
||||
@@ -106,6 +107,14 @@ class SplitDateTimePickerWidget(forms.SplitDateTimeWidget):
|
||||
time_attrs['class'] += ' timepickerfield'
|
||||
date_attrs['autocomplete'] = 'date-picker-do-not-autofill'
|
||||
time_attrs['autocomplete'] = 'time-picker-do-not-autofill'
|
||||
if min_date:
|
||||
date_attrs['data-min'] = (
|
||||
min_date if isinstance(min_date, date) else min_date.astimezone(get_current_timezone()).date()
|
||||
).isoformat()
|
||||
if max_date:
|
||||
date_attrs['data-max'] = (
|
||||
max_date if isinstance(max_date, date) else max_date.astimezone(get_current_timezone()).date()
|
||||
).isoformat()
|
||||
|
||||
def date_placeholder():
|
||||
df = date_format or get_format('DATE_INPUT_FORMATS')[0]
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Generated by Django 3.0.11 on 2020-12-18 18:10
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0162_remove_seat_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='cachedfile',
|
||||
name='session_key',
|
||||
field=models.TextField(null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cachedfile',
|
||||
name='web_download',
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
]
|
||||
49
src/pretix/base/migrations/0171_auto_20201126_1635.py
Normal file
49
src/pretix/base/migrations/0171_auto_20201126_1635.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# Generated by Django 3.0.11 on 2020-11-26 16:35
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0170_remove_hidden_urls'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='question',
|
||||
name='valid_date_max',
|
||||
field=models.DateField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='question',
|
||||
name='valid_date_min',
|
||||
field=models.DateField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='question',
|
||||
name='valid_datetime_max',
|
||||
field=models.DateTimeField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='question',
|
||||
name='valid_datetime_min',
|
||||
field=models.DateTimeField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='question',
|
||||
name='valid_number_max',
|
||||
field=models.DecimalField(decimal_places=6, max_digits=16, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='question',
|
||||
name='valid_number_min',
|
||||
field=models.DecimalField(decimal_places=6, max_digits=16, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='seat',
|
||||
name='product',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='seats', to='pretixbase.Item'),
|
||||
),
|
||||
]
|
||||
@@ -1,14 +0,0 @@
|
||||
# Generated by Django 3.0.11 on 2020-12-22 10:30
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0170_remove_hidden_urls'),
|
||||
('pretixbase', '0162b_auto_20201218_1810'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
]
|
||||
20
src/pretix/base/migrations/0172_event_sales_channels.py
Normal file
20
src/pretix/base/migrations/0172_event_sales_channels.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# Generated by Django 3.0.9 on 2020-12-02 12:37
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
import pretix.base.models.fields
|
||||
from pretix.base.channels import get_all_sales_channels
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('pretixbase', '0171_auto_20201126_1635'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='sales_channels',
|
||||
field=pretix.base.models.fields.MultiStringField(default=list(get_all_sales_channels().keys())),
|
||||
),
|
||||
]
|
||||
@@ -28,8 +28,6 @@ class CachedFile(models.Model):
|
||||
filename = models.CharField(max_length=255)
|
||||
type = models.CharField(max_length=255)
|
||||
file = models.FileField(null=True, blank=True, upload_to=cachedfile_name, max_length=255)
|
||||
web_download = models.BooleanField(default=True) # allow web download, True for backwards compatibility in plugins
|
||||
session_key = models.TextField(null=True, blank=True) # only allow download in this session
|
||||
|
||||
|
||||
@receiver(post_delete, sender=CachedFile)
|
||||
|
||||
@@ -20,7 +20,7 @@ class CheckinList(LoggedModel):
|
||||
include_pending = models.BooleanField(verbose_name=pgettext_lazy('checkin', 'Include pending orders'),
|
||||
default=False,
|
||||
help_text=_('With this option, people will be able to check in even if the '
|
||||
'order have not been paid.'))
|
||||
'order has not been paid.'))
|
||||
gates = models.ManyToManyField(
|
||||
'Gate', verbose_name=_("Gates"), blank=True,
|
||||
help_text=_("Does not have any effect for the validation of tickets, only for the automatic configuration of "
|
||||
|
||||
@@ -23,6 +23,7 @@ from django_scopes import ScopedManager, scopes_disabled
|
||||
from i18nfield.fields import I18nCharField, I18nTextField
|
||||
|
||||
from pretix.base.models.base import LoggedModel
|
||||
from pretix.base.models.fields import MultiStringField
|
||||
from pretix.base.reldate import RelativeDateWrapper
|
||||
from pretix.base.validators import EventSlugBanlistValidator
|
||||
from pretix.helpers.database import GroupConcat
|
||||
@@ -331,6 +332,8 @@ class Event(EventMixin, LoggedModel):
|
||||
:type plugins: str
|
||||
:param has_subevents: Enable event series functionality
|
||||
:type has_subevents: bool
|
||||
:param sales_channels: A list of sales channel identifiers, that this event is available for sale on
|
||||
:type sales_channels: list
|
||||
"""
|
||||
|
||||
settings_namespace = 'event'
|
||||
@@ -409,7 +412,11 @@ class Event(EventMixin, LoggedModel):
|
||||
)
|
||||
seating_plan = models.ForeignKey('SeatingPlan', on_delete=models.PROTECT, null=True, blank=True,
|
||||
related_name='events')
|
||||
|
||||
sales_channels = MultiStringField(
|
||||
verbose_name=_('Restrict to specific sales channels'),
|
||||
help_text=_('Only sell tickets for this event on the following sales channels.'),
|
||||
default=['web'],
|
||||
)
|
||||
objects = ScopedManager(organizer='organizer')
|
||||
|
||||
class Meta:
|
||||
|
||||
@@ -1084,6 +1084,18 @@ class Question(LoggedModel):
|
||||
'Question', null=True, blank=True, on_delete=models.SET_NULL, related_name='dependent_questions'
|
||||
)
|
||||
dependency_values = MultiStringField(default=[])
|
||||
valid_number_min = models.DecimalField(decimal_places=6, max_digits=16, null=True, blank=True,
|
||||
verbose_name=_('Minimum value'), help_text=_('Currently not supported in our apps'))
|
||||
valid_number_max = models.DecimalField(decimal_places=6, max_digits=16, null=True, blank=True,
|
||||
verbose_name=_('Maximum value'), help_text=_('Currently not supported in our apps'))
|
||||
valid_date_min = models.DateField(null=True, blank=True,
|
||||
verbose_name=_('Minimum value'), help_text=_('Currently not supported in our apps'))
|
||||
valid_date_max = models.DateField(null=True, blank=True,
|
||||
verbose_name=_('Maximum value'), help_text=_('Currently not supported in our apps'))
|
||||
valid_datetime_min = models.DateTimeField(null=True, blank=True,
|
||||
verbose_name=_('Minimum value'), help_text=_('Currently not supported in our apps'))
|
||||
valid_datetime_max = models.DateTimeField(null=True, blank=True,
|
||||
verbose_name=_('Maximum value'), help_text=_('Currently not supported in our apps'))
|
||||
|
||||
objects = ScopedManager(organizer='event__organizer')
|
||||
|
||||
@@ -1173,14 +1185,24 @@ class Question(LoggedModel):
|
||||
answer = formats.sanitize_separators(answer)
|
||||
answer = str(answer).strip()
|
||||
try:
|
||||
return Decimal(answer)
|
||||
v = Decimal(answer)
|
||||
if self.valid_number_min is not None and v < self.valid_number_min:
|
||||
raise ValidationError(_('The number is to low.'))
|
||||
if self.valid_number_max is not None and v > self.valid_number_max:
|
||||
raise ValidationError(_('The number is to high.'))
|
||||
return v
|
||||
except DecimalException:
|
||||
raise ValidationError(_('Invalid number input.'))
|
||||
elif self.type == Question.TYPE_DATE:
|
||||
if isinstance(answer, date):
|
||||
return answer
|
||||
try:
|
||||
return dateutil.parser.parse(answer).date()
|
||||
dt = dateutil.parser.parse(answer).date()
|
||||
if self.valid_date_min is not None and dt < self.valid_date_min:
|
||||
raise ValidationError(_('Please choose a later date.'))
|
||||
if self.valid_date_max is not None and dt > self.valid_date_max:
|
||||
raise ValidationError(_('Please choose an earlier date.'))
|
||||
return dt
|
||||
except:
|
||||
raise ValidationError(_('Invalid date input.'))
|
||||
elif self.type == Question.TYPE_TIME:
|
||||
@@ -1197,9 +1219,14 @@ class Question(LoggedModel):
|
||||
dt = dateutil.parser.parse(answer)
|
||||
if is_naive(dt):
|
||||
dt = make_aware(dt, pytz.timezone(self.event.settings.timezone))
|
||||
return dt
|
||||
except:
|
||||
raise ValidationError(_('Invalid datetime input.'))
|
||||
else:
|
||||
if self.valid_datetime_min is not None and dt < self.valid_datetime_min:
|
||||
raise ValidationError(_('Please choose a later date.'))
|
||||
if self.valid_datetime_max is not None and dt > self.valid_datetime_max:
|
||||
raise ValidationError(_('Please choose an earlier date.'))
|
||||
return dt
|
||||
elif self.type == Question.TYPE_COUNTRYCODE and answer:
|
||||
c = Country(answer.upper())
|
||||
if c.name:
|
||||
|
||||
@@ -639,7 +639,7 @@ class Order(LockModel, LoggedModel):
|
||||
return
|
||||
|
||||
if iteration > 20:
|
||||
# Safeguard: If we don't find an unused and non-blacklisted code within 20 iterations, we increase
|
||||
# Safeguard: If we don't find an unused and non-banlisted code within 20 iterations, we increase
|
||||
# the length.
|
||||
length += 1
|
||||
iteration = 0
|
||||
@@ -1874,7 +1874,7 @@ class OrderFee(models.Model):
|
||||
self.tax_rule = self.order.event.settings.tax_rate_default
|
||||
|
||||
if self.tax_rule:
|
||||
tax = self.tax_rule.tax(self.value, base_price_is='gross', invoice_address=ia)
|
||||
tax = self.tax_rule.tax(self.value, base_price_is='gross', invoice_address=ia, force_fixed_gross_price=True)
|
||||
self.tax_rate = tax.rate
|
||||
self.tax_value = tax.tax
|
||||
else:
|
||||
@@ -2026,9 +2026,11 @@ class OrderPosition(AbstractPosition):
|
||||
except InvoiceAddress.DoesNotExist:
|
||||
ia = None
|
||||
if self.tax_rule:
|
||||
tax = self.tax_rule.tax(self.price, invoice_address=ia, base_price_is='gross')
|
||||
tax = self.tax_rule.tax(self.price, invoice_address=ia, base_price_is='gross', force_fixed_gross_price=True)
|
||||
self.tax_rate = tax.rate
|
||||
self.tax_value = tax.tax
|
||||
if tax.gross != self.price:
|
||||
raise ValueError('Invalid tax calculation')
|
||||
else:
|
||||
self.tax_value = Decimal('0.00')
|
||||
self.tax_rate = Decimal('0.00')
|
||||
@@ -2038,6 +2040,7 @@ class OrderPosition(AbstractPosition):
|
||||
|
||||
if self.tax_rate is None:
|
||||
self._calculate_tax()
|
||||
|
||||
self.order.touch()
|
||||
if not self.pk:
|
||||
while not self.secret or OrderPosition.all.filter(
|
||||
|
||||
@@ -5,8 +5,9 @@ from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.utils.formats import localize
|
||||
from django.utils.timezone import get_current_timezone, now
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _, pgettext
|
||||
from i18nfield.fields import I18nCharField
|
||||
from i18nfield.strings import LazyI18nString
|
||||
|
||||
from pretix.base.decimal import round_decimal
|
||||
from pretix.base.models.base import LoggedModel
|
||||
@@ -188,7 +189,7 @@ class TaxRule(LoggedModel):
|
||||
return Decimal(self.rate)
|
||||
|
||||
def tax(self, base_price, base_price_is='auto', currency=None, override_tax_rate=None, invoice_address=None,
|
||||
subtract_from_gross=Decimal('0.00'), gross_price_is_tax_rate: Decimal = None):
|
||||
subtract_from_gross=Decimal('0.00'), gross_price_is_tax_rate: Decimal = None, force_fixed_gross_price=False):
|
||||
from .event import Event
|
||||
try:
|
||||
currency = currency or self.event.currency
|
||||
@@ -200,7 +201,7 @@ class TaxRule(LoggedModel):
|
||||
rate = override_tax_rate
|
||||
elif invoice_address:
|
||||
adjust_rate = self.tax_rate_for(invoice_address)
|
||||
if adjust_rate == gross_price_is_tax_rate and base_price_is == 'gross':
|
||||
if (adjust_rate == gross_price_is_tax_rate or force_fixed_gross_price) and base_price_is == 'gross':
|
||||
rate = adjust_rate
|
||||
elif adjust_rate != rate:
|
||||
normal_price = self.tax(base_price, base_price_is, currency, subtract_from_gross=subtract_from_gross)
|
||||
@@ -268,6 +269,25 @@ class TaxRule(LoggedModel):
|
||||
return r
|
||||
return {'action': 'vat'}
|
||||
|
||||
def invoice_text(self, invoice_address):
|
||||
if self._custom_rules:
|
||||
rule = self.get_matching_rule(invoice_address)
|
||||
t = rule.get('invoice_text', {})
|
||||
if t and any(l for l in t.values()):
|
||||
return str(LazyI18nString(t))
|
||||
if self.is_reverse_charge(invoice_address):
|
||||
if is_eu_country(invoice_address.country):
|
||||
return pgettext(
|
||||
"invoice",
|
||||
"Reverse Charge: According to Article 194, 196 of Council Directive 2006/112/EEC, VAT liability "
|
||||
"rests with the service recipient."
|
||||
)
|
||||
else:
|
||||
return pgettext(
|
||||
"invoice",
|
||||
"VAT liability rests with the service recipient."
|
||||
)
|
||||
|
||||
def is_reverse_charge(self, invoice_address):
|
||||
if self._custom_rules:
|
||||
rule = self.get_matching_rule(invoice_address)
|
||||
|
||||
@@ -121,6 +121,26 @@ DEFAULT_VARIABLES = OrderedDict((
|
||||
'editor_sample': _('John Doe\nSample company\nSesame Street 42\n12345 Any City\nAtlantis'),
|
||||
'evaluate': lambda op, order, event: op.address_format()
|
||||
}),
|
||||
("attendee_street", {
|
||||
"label": _("Attendee street"),
|
||||
"editor_sample": 'Sesame Street 42',
|
||||
"evaluate": lambda op, order, ev: op.street or (op.addon_to.street if op.addon_to else '')
|
||||
}),
|
||||
("attendee_zipcode", {
|
||||
"label": _("Attendee ZIP code"),
|
||||
"editor_sample": '12345',
|
||||
"evaluate": lambda op, order, ev: op.zipcode or (op.addon_to.zipcode if op.addon_to else '')
|
||||
}),
|
||||
("attendee_city", {
|
||||
"label": _("Attendee city"),
|
||||
"editor_sample": 'Any City',
|
||||
"evaluate": lambda op, order, ev: op.city or (op.addon_to.city if op.addon_to else '')
|
||||
}),
|
||||
("attendee_state", {
|
||||
"label": _("Attendee state"),
|
||||
"editor_sample": 'Sample State',
|
||||
"evaluate": lambda op, order, ev: op.state or (op.addon_to.state if op.addon_to else '')
|
||||
}),
|
||||
("attendee_country", {
|
||||
"label": _("Attendee country"),
|
||||
"editor_sample": 'Atlantis',
|
||||
@@ -219,11 +239,31 @@ DEFAULT_VARIABLES = OrderedDict((
|
||||
"editor_sample": _("Sample company"),
|
||||
"evaluate": lambda op, order, ev: order.invoice_address.company if getattr(order, 'invoice_address', None) else ''
|
||||
}),
|
||||
("invoice_street", {
|
||||
"label": _("Invoice address street"),
|
||||
"editor_sample": _("Sesame Street 42"),
|
||||
"evaluate": lambda op, order, ev: order.invoice_address.street if getattr(order, 'invoice_address', None) else ''
|
||||
}),
|
||||
("invoice_zipcode", {
|
||||
"label": _("Invoice address ZIP code"),
|
||||
"editor_sample": _("12345"),
|
||||
"evaluate": lambda op, order, ev: order.invoice_address.zipcode if getattr(order, 'invoice_address', None) else ''
|
||||
}),
|
||||
("invoice_city", {
|
||||
"label": _("Invoice address city"),
|
||||
"editor_sample": _("Sample city"),
|
||||
"evaluate": lambda op, order, ev: order.invoice_address.city if getattr(order, 'invoice_address', None) else ''
|
||||
}),
|
||||
("invoice_state", {
|
||||
"label": _("Invoice address state"),
|
||||
"editor_sample": _("Sample State"),
|
||||
"evaluate": lambda op, order, ev: order.invoice_address.state if getattr(order, 'invoice_address', None) else ''
|
||||
}),
|
||||
("invoice_country", {
|
||||
"label": _("Invoice address country"),
|
||||
"editor_sample": _("Atlantis"),
|
||||
"evaluate": lambda op, order, ev: str(getattr(order.invoice_address.country, 'name', '')) if getattr(order, 'invoice_address', None) else ''
|
||||
}),
|
||||
("addons", {
|
||||
"label": _("List of Add-Ons"),
|
||||
"editor_sample": _("Add-on 1\nAdd-on 2"),
|
||||
|
||||
@@ -24,7 +24,7 @@ from pretix.base.i18n import language
|
||||
from pretix.base.models import (
|
||||
Invoice, InvoiceAddress, InvoiceLine, Order, OrderFee,
|
||||
)
|
||||
from pretix.base.models.tax import EU_CURRENCIES, is_eu_country
|
||||
from pretix.base.models.tax import EU_CURRENCIES
|
||||
from pretix.base.services.tasks import TransactionAwareTask
|
||||
from pretix.base.settings import GlobalSettingsObject
|
||||
from pretix.base.signals import invoice_line_text, periodic_task
|
||||
@@ -142,6 +142,8 @@ def build_invoice(invoice: Invoice) -> Invoice:
|
||||
reverse_charge = False
|
||||
|
||||
positions.sort(key=lambda p: p.sort_key)
|
||||
|
||||
tax_texts = []
|
||||
for i, p in enumerate(positions):
|
||||
if not invoice.event.settings.invoice_include_free and p.price == Decimal('0.00') and not p.addon_c:
|
||||
continue
|
||||
@@ -178,22 +180,10 @@ def build_invoice(invoice: Invoice) -> Invoice:
|
||||
if p.tax_rule and p.tax_rule.is_reverse_charge(ia) and p.price and not p.tax_value:
|
||||
reverse_charge = True
|
||||
|
||||
if reverse_charge:
|
||||
if invoice.additional_text:
|
||||
invoice.additional_text += "<br /><br />"
|
||||
if is_eu_country(invoice.invoice_to_country):
|
||||
invoice.additional_text += pgettext(
|
||||
"invoice",
|
||||
"Reverse Charge: According to Article 194, 196 of Council Directive 2006/112/EEC, VAT liability "
|
||||
"rests with the service recipient."
|
||||
)
|
||||
else:
|
||||
invoice.additional_text += pgettext(
|
||||
"invoice",
|
||||
"VAT liability rests with the service recipient."
|
||||
)
|
||||
invoice.reverse_charge = True
|
||||
invoice.save()
|
||||
if p.tax_rule:
|
||||
tax_text = p.tax_rule.invoice_text(ia)
|
||||
if tax_text and tax_text not in tax_texts:
|
||||
tax_texts.append(tax_text)
|
||||
|
||||
offset = len(positions)
|
||||
for i, fee in enumerate(invoice.order.fees.all()):
|
||||
@@ -213,6 +203,20 @@ def build_invoice(invoice: Invoice) -> Invoice:
|
||||
tax_name=fee.tax_rule.name if fee.tax_rule else ''
|
||||
)
|
||||
|
||||
if fee.tax_rule and fee.tax_rule.is_reverse_charge(ia) and fee.value and not fee.tax_value:
|
||||
reverse_charge = True
|
||||
|
||||
if fee.tax_rule:
|
||||
tax_text = fee.tax_rule.invoice_text(ia)
|
||||
if tax_text and tax_text not in tax_texts:
|
||||
tax_texts.append(tax_text)
|
||||
|
||||
if tax_texts:
|
||||
invoice.additional_text += "<br /><br />"
|
||||
invoice.additional_text += "<br />".join(tax_texts)
|
||||
invoice.reverse_charge = reverse_charge
|
||||
invoice.save()
|
||||
|
||||
return invoice
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ from pretix.celery_app import app
|
||||
|
||||
|
||||
@app.task(base=ProfiledEventTask)
|
||||
def export(event: Event, shredders: List[str], session_key=None) -> None:
|
||||
def export(event: Event, shredders: List[str]) -> None:
|
||||
known_shredders = event.get_data_shredders()
|
||||
|
||||
with NamedTemporaryFile() as rawfile:
|
||||
@@ -55,8 +55,6 @@ def export(event: Event, shredders: List[str], session_key=None) -> None:
|
||||
cf.date = now()
|
||||
cf.filename = event.slug + '.zip'
|
||||
cf.type = 'application/zip'
|
||||
cf.session_key = session_key
|
||||
cf.web_download = True
|
||||
cf.expires = now() + timedelta(hours=1)
|
||||
cf.save()
|
||||
cf.file.save(cachedfile_name(cf, cf.filename), rawfile)
|
||||
|
||||
@@ -9,7 +9,9 @@ from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.files import File
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.core.validators import (
|
||||
MaxValueValidator, MinValueValidator, RegexValidator,
|
||||
)
|
||||
from django.db.models import Model
|
||||
from django.utils.translation import (
|
||||
gettext_lazy as _, gettext_noop, pgettext, pgettext_lazy,
|
||||
@@ -26,7 +28,9 @@ from pretix.base.reldate import (
|
||||
RelativeDateField, RelativeDateTimeField, RelativeDateWrapper,
|
||||
SerializerRelativeDateField, SerializerRelativeDateTimeField,
|
||||
)
|
||||
from pretix.control.forms import MultipleLanguagesWidget, SingleLanguageWidget
|
||||
from pretix.control.forms import (
|
||||
FontSelect, MultipleLanguagesWidget, SingleLanguageWidget,
|
||||
)
|
||||
from pretix.helpers.countries import CachedCountries
|
||||
|
||||
|
||||
@@ -38,6 +42,18 @@ def country_choice_kwargs():
|
||||
}
|
||||
|
||||
|
||||
def primary_font_kwargs():
|
||||
from pretix.presale.style import get_fonts
|
||||
|
||||
choices = [('Open Sans', 'Open Sans')]
|
||||
choices += [
|
||||
(a, {"title": a, "data": v}) for a, v in get_fonts().items()
|
||||
]
|
||||
return {
|
||||
'choices': choices,
|
||||
}
|
||||
|
||||
|
||||
class LazyI18nStringList(UserList):
|
||||
def __init__(self, init_list=None):
|
||||
super().__init__()
|
||||
@@ -252,7 +268,6 @@ DEFAULTS = {
|
||||
'form_kwargs': dict(
|
||||
label=_("Ask for beneficiary"),
|
||||
widget=forms.CheckboxInput(attrs={'data-checkbox-dependency': '#id_invoice_address_asked'}),
|
||||
required=False
|
||||
)
|
||||
},
|
||||
'invoice_address_custom_field': {
|
||||
@@ -421,7 +436,6 @@ DEFAULTS = {
|
||||
widget_kwargs={'attrs': {
|
||||
'rows': 3,
|
||||
}},
|
||||
required=False,
|
||||
label=_("Guidance text"),
|
||||
help_text=_("This text will be shown above the payment options. You can explain the choices to the user here, "
|
||||
"if you want.")
|
||||
@@ -441,7 +455,6 @@ DEFAULTS = {
|
||||
'form_kwargs': dict(
|
||||
label=_("Set payment term"),
|
||||
widget=forms.RadioSelect,
|
||||
required=True,
|
||||
choices=(
|
||||
('days', _("in days")),
|
||||
('minutes', _("in minutes"))
|
||||
@@ -488,7 +501,6 @@ DEFAULTS = {
|
||||
widget=forms.CheckboxInput(
|
||||
attrs={
|
||||
'data-display-dependency': '#id_payment_term_mode_0',
|
||||
'data-required-if': '#id_payment_term_mode_0'
|
||||
},
|
||||
),
|
||||
)
|
||||
@@ -541,6 +553,18 @@ DEFAULTS = {
|
||||
"the pool and can be ordered by other people."),
|
||||
)
|
||||
},
|
||||
'payment_pending_hidden': {
|
||||
'default': 'False',
|
||||
'type': bool,
|
||||
'form_class': forms.BooleanField,
|
||||
'serializer_class': serializers.BooleanField,
|
||||
'form_kwargs': dict(
|
||||
label=_('Hide "payment pending" state on customer-facing pages'),
|
||||
help_text=_("The payment instructions panel will still be shown to the primary customer, but no indication "
|
||||
"of missing payment will be visible on the ticket pages of attendees who did not buy the ticket "
|
||||
"themselves.")
|
||||
)
|
||||
},
|
||||
'payment_giftcard__enabled': {
|
||||
'default': 'True',
|
||||
'type': bool
|
||||
@@ -990,7 +1014,16 @@ DEFAULTS = {
|
||||
},
|
||||
'event_list_availability': {
|
||||
'default': 'True',
|
||||
'type': bool
|
||||
'type': bool,
|
||||
'serializer_class': serializers.BooleanField,
|
||||
'form_class': forms.BooleanField,
|
||||
'form_kwargs': dict(
|
||||
label=_('Show availability in event overviews'),
|
||||
help_text=_('If checked, the list of events will show if events are sold out. This might '
|
||||
'make for longer page loading times if you have lots of events and the shown status might be out '
|
||||
'of date for up to two minutes.'),
|
||||
required=False
|
||||
)
|
||||
},
|
||||
'event_list_type': {
|
||||
'default': 'list',
|
||||
@@ -1599,26 +1632,106 @@ Your {event} team"""))
|
||||
'primary_color': {
|
||||
'default': settings.PRETIX_PRIMARY_COLOR,
|
||||
'type': str,
|
||||
'form_class': forms.CharField,
|
||||
'serializer_class': serializers.CharField,
|
||||
'serializer_kwargs': dict(
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
],
|
||||
),
|
||||
'form_kwargs': dict(
|
||||
label=_("Primary color"),
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
),
|
||||
},
|
||||
'theme_color_success': {
|
||||
'default': '#50A167',
|
||||
'type': str
|
||||
'type': str,
|
||||
'form_class': forms.CharField,
|
||||
'serializer_class': serializers.CharField,
|
||||
'serializer_kwargs': dict(
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
],
|
||||
),
|
||||
'form_kwargs': dict(
|
||||
label=_("Accent color for success"),
|
||||
help_text=_("We strongly suggest to use a shade of green."),
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
),
|
||||
},
|
||||
'theme_color_danger': {
|
||||
'default': '#D36060',
|
||||
'type': str
|
||||
'type': str,
|
||||
'form_class': forms.CharField,
|
||||
'serializer_class': serializers.CharField,
|
||||
'serializer_kwargs': dict(
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
],
|
||||
),
|
||||
'form_kwargs': dict(
|
||||
label=_("Accent color for errors"),
|
||||
help_text=_("We strongly suggest to use a shade of red."),
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
),
|
||||
},
|
||||
'theme_color_background': {
|
||||
'default': '#FFFFFF',
|
||||
'type': str
|
||||
'type': str,
|
||||
'form_class': forms.CharField,
|
||||
'serializer_class': serializers.CharField,
|
||||
'serializer_kwargs': dict(
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
],
|
||||
),
|
||||
'form_kwargs': dict(
|
||||
label=_("Page background color"),
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield no-contrast'})
|
||||
),
|
||||
},
|
||||
'theme_round_borders': {
|
||||
'default': 'True',
|
||||
'type': bool
|
||||
'type': bool,
|
||||
'form_class': forms.BooleanField,
|
||||
'serializer_class': serializers.BooleanField,
|
||||
'form_kwargs': dict(
|
||||
label=_("Use round edges"),
|
||||
)
|
||||
},
|
||||
'primary_font': {
|
||||
'default': 'Open Sans',
|
||||
'type': str
|
||||
'type': str,
|
||||
'form_class': forms.ChoiceField,
|
||||
'serializer_class': serializers.ChoiceField,
|
||||
'serializer_kwargs': lambda: dict(**primary_font_kwargs()),
|
||||
'form_kwargs': lambda: dict(
|
||||
label=_('Font'),
|
||||
help_text=_('Only respected by modern browsers.'),
|
||||
widget=FontSelect,
|
||||
**primary_font_kwargs()
|
||||
),
|
||||
},
|
||||
'presale_css_file': {
|
||||
'default': None,
|
||||
@@ -1654,7 +1767,13 @@ Your {event} team"""))
|
||||
},
|
||||
'organizer_logo_image_large': {
|
||||
'default': 'False',
|
||||
'type': bool
|
||||
'type': bool,
|
||||
'form_class': forms.BooleanField,
|
||||
'serializer_class': serializers.BooleanField,
|
||||
'form_kwargs': dict(
|
||||
label=_('Use header image in its full size'),
|
||||
help_text=_('We recommend to upload a picture at least 1170 pixels wide.'),
|
||||
)
|
||||
},
|
||||
'og_image': {
|
||||
'default': None,
|
||||
@@ -1713,6 +1832,19 @@ Your {event} team"""))
|
||||
"how to obtain a voucher code.")
|
||||
)
|
||||
},
|
||||
'attendee_data_explanation_text': {
|
||||
'default': '',
|
||||
'type': LazyI18nString,
|
||||
'serializer_class': I18nField,
|
||||
'form_class': I18nFormField,
|
||||
'form_kwargs': dict(
|
||||
label=_("Attendee data explanation"),
|
||||
widget=I18nTextarea,
|
||||
widget_kwargs={'attrs': {'rows': '2'}},
|
||||
help_text=_("This text will be shown above the questions asked for every admission product. You can use it e.g. to explain "
|
||||
"why you need information from them.")
|
||||
)
|
||||
},
|
||||
'checkout_email_helptext': {
|
||||
'default': LazyI18nString.from_gettext(gettext_noop(
|
||||
'Make sure to enter a valid email address. We will send you an order '
|
||||
@@ -1733,11 +1865,26 @@ Your {event} team"""))
|
||||
},
|
||||
'organizer_info_text': {
|
||||
'default': '',
|
||||
'type': LazyI18nString
|
||||
'type': LazyI18nString,
|
||||
'serializer_class': I18nField,
|
||||
'form_class': I18nFormField,
|
||||
'form_kwargs': dict(
|
||||
label=_('Info text'),
|
||||
widget=I18nTextarea,
|
||||
help_text=_('Not displayed anywhere by default, but if you want to, you can use this e.g. in ticket templates.')
|
||||
)
|
||||
},
|
||||
'event_team_provisioning': {
|
||||
'default': 'True',
|
||||
'type': bool
|
||||
'type': bool,
|
||||
'form_class': forms.BooleanField,
|
||||
'serializer_class': serializers.BooleanField,
|
||||
'form_kwargs': dict(
|
||||
label=_('Allow creating a new team during event creation'),
|
||||
help_text=_('Users that do not have access to all events under this organizer, must select one of their teams '
|
||||
'to have access to the created event. This setting allows users to create an event-specified team'
|
||||
' on-the-fly, even when they do not have \"Can change teams and permissions\" permission.'),
|
||||
)
|
||||
},
|
||||
'update_check_ack': {
|
||||
'default': 'False',
|
||||
@@ -1779,6 +1926,10 @@ Your {event} team"""))
|
||||
'default': None,
|
||||
'type': str
|
||||
},
|
||||
'mapquest_apikey': {
|
||||
'default': None,
|
||||
'type': str
|
||||
},
|
||||
'leaflet_tiles': {
|
||||
'default': None,
|
||||
'type': str
|
||||
@@ -1811,13 +1962,51 @@ Your {event} team"""))
|
||||
# When adding a new ordering, remember to also define it in the event model
|
||||
)
|
||||
},
|
||||
'organizer_link_back': {
|
||||
'default': 'False',
|
||||
'type': bool,
|
||||
'form_class': forms.BooleanField,
|
||||
'serializer_class': serializers.BooleanField,
|
||||
'form_kwargs': dict(
|
||||
label=_('Link back to organizer overview on all event pages'),
|
||||
)
|
||||
},
|
||||
'organizer_homepage_text': {
|
||||
'default': '',
|
||||
'type': LazyI18nString,
|
||||
'serializer_class': I18nField,
|
||||
'form_class': I18nFormField,
|
||||
'form_kwargs': dict(
|
||||
label=_('Homepage text'),
|
||||
widget=I18nTextarea,
|
||||
help_text=_('This will be displayed on the organizer homepage.')
|
||||
)
|
||||
},
|
||||
'name_scheme': {
|
||||
'default': 'full',
|
||||
'type': str
|
||||
},
|
||||
'giftcard_length': {
|
||||
'default': settings.ENTROPY['giftcard_secret'],
|
||||
'type': int
|
||||
'type': int,
|
||||
'form_class': forms.IntegerField,
|
||||
'serializer_class': serializers.IntegerField,
|
||||
'form_kwargs': dict(
|
||||
label=_('Length of gift card codes'),
|
||||
help_text=_('The system generates by default {}-character long gift card codes. However, if a different length '
|
||||
'is required, it can be set here.'.format(settings.ENTROPY['giftcard_secret'])),
|
||||
)
|
||||
},
|
||||
'giftcard_expiry_years': {
|
||||
'default': None,
|
||||
'type': int,
|
||||
'form_class': forms.IntegerField,
|
||||
'serializer_class': serializers.IntegerField,
|
||||
'form_kwargs': dict(
|
||||
label=_('Validity of gift card codes in years'),
|
||||
help_text=_('If you set a number here, gift cards will by default expire at the end of the year after this '
|
||||
'many years. If you keep it empty, gift cards do not have an explicit expiry date.'),
|
||||
)
|
||||
},
|
||||
'seating_choice': {
|
||||
'default': 'True',
|
||||
@@ -1853,6 +2042,10 @@ Your {event} team"""))
|
||||
),
|
||||
}
|
||||
}
|
||||
SETTINGS_AFFECTING_CSS = {
|
||||
'primary_color', 'theme_color_success', 'theme_color_danger', 'primary_font',
|
||||
'theme_color_background', 'theme_round_borders'
|
||||
}
|
||||
PERSON_NAME_TITLE_GROUPS = OrderedDict([
|
||||
('english_common', (_('Most common English titles'), (
|
||||
'Mr',
|
||||
@@ -2052,6 +2245,30 @@ PERSON_NAME_SCHEMES = OrderedDict([
|
||||
'_scheme': 'salutation_title_given_family',
|
||||
},
|
||||
}),
|
||||
('salutation_title_given_family_degree', {
|
||||
'fields': (
|
||||
('salutation', pgettext_lazy('person_name', 'Salutation'), 1),
|
||||
('title', pgettext_lazy('person_name', 'Title'), 1),
|
||||
('given_name', _('Given name'), 2),
|
||||
('family_name', _('Family name'), 2),
|
||||
('degree', pgettext_lazy('person_name', 'Degree (after name)'), 2),
|
||||
),
|
||||
'concatenation': lambda d: (
|
||||
' '.join(
|
||||
str(p) for p in (d.get(key, '') for key in ["title", "given_name", "family_name"]) if p
|
||||
) +
|
||||
str((', ' if d.get('degree') else '')) +
|
||||
str(d.get('degree', ''))
|
||||
),
|
||||
'sample': {
|
||||
'salutation': pgettext_lazy('person_name_sample', 'Mr'),
|
||||
'title': pgettext_lazy('person_name_sample', 'Dr'),
|
||||
'given_name': pgettext_lazy('person_name_sample', 'John'),
|
||||
'family_name': pgettext_lazy('person_name_sample', 'Doe'),
|
||||
'degree': pgettext_lazy('person_name_sample', 'MA'),
|
||||
'_scheme': 'salutation_title_given_family_degree',
|
||||
},
|
||||
}),
|
||||
])
|
||||
COUNTRIES_WITH_STATE_IN_ADDRESS = {
|
||||
# Source: http://www.bitboost.com/ref/international-address-formats.html
|
||||
@@ -2143,7 +2360,8 @@ class SettingsSandbox:
|
||||
self._event.settings.set(self._convert_key(key), value)
|
||||
|
||||
|
||||
def validate_settings(event, settings_dict):
|
||||
def validate_event_settings(event, settings_dict):
|
||||
from pretix.base.models import Event
|
||||
from pretix.base.signals import validate_event_settings
|
||||
|
||||
if 'locales' in settings_dict and settings_dict['locale'] not in settings_dict['locales']:
|
||||
@@ -2174,4 +2392,14 @@ def validate_settings(event, settings_dict):
|
||||
'payment_term_last': _('The last payment date cannot be before the end of presale.')
|
||||
})
|
||||
|
||||
validate_event_settings.send(sender=event, settings_dict=settings_dict)
|
||||
if isinstance(event, Event):
|
||||
validate_event_settings.send(sender=event, settings_dict=settings_dict)
|
||||
|
||||
|
||||
def validate_organizer_settings(organizer, settings_dict):
|
||||
# This is not doing anything for the time being.
|
||||
# But earlier we called validate_event_settings for the organizer, too - and that didn't do anything for
|
||||
# organizer-settings either.
|
||||
#
|
||||
# N.B.: When actually fleshing out this stub, adding it to the OrganizerUpdateForm should be considered.
|
||||
pass
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import re
|
||||
import urllib.parse
|
||||
|
||||
import bleach
|
||||
@@ -72,10 +71,6 @@ EMAIL_RE = build_email_re(tlds=sorted(tld_set, key=len, reverse=True))
|
||||
|
||||
|
||||
def safelink_callback(attrs, new=False):
|
||||
"""
|
||||
Makes sure that all links to a different domain are passed through a redirection handler
|
||||
to ensure there's no passing of referers with secrets inside them.
|
||||
"""
|
||||
url = attrs.get((None, 'href'), '/')
|
||||
if not url_has_allowed_host_and_scheme(url, allowed_hosts=None) and not url.startswith('mailto:') and not url.startswith('tel:'):
|
||||
signer = signing.Signer(salt='safe-redirect')
|
||||
@@ -85,42 +80,7 @@ def safelink_callback(attrs, new=False):
|
||||
return attrs
|
||||
|
||||
|
||||
def truelink_callback(attrs, new=False):
|
||||
"""
|
||||
Tries to prevent "phishing" attacks in which a link looks like it points to a safe place but instead
|
||||
points somewhere else, e.g.
|
||||
|
||||
<a href="https://evilsite.com">https://google.com</a>
|
||||
|
||||
At the same time, custom texts are still allowed:
|
||||
|
||||
<a href="https://maps.google.com">Get to the event</a>
|
||||
|
||||
Suffixes are also allowed:
|
||||
|
||||
<a href="https://maps.google.com/location/foo">https://maps.google.com</a>
|
||||
"""
|
||||
text = re.sub('[^a-zA-Z0-9.-/_]', '', attrs.get('_text')) # clean up link text
|
||||
if URL_RE.match(text):
|
||||
# link text looks like a url
|
||||
if text.startswith('//'):
|
||||
text = 'https:' + text
|
||||
elif not text.startswith('http'):
|
||||
text = 'https://' + text
|
||||
|
||||
text_url = urllib.parse.urlparse(text)
|
||||
href_url = urllib.parse.urlparse(attrs[None, 'href'])
|
||||
if text_url.netloc != href_url.netloc or not href_url.path.startswith(href_url.path):
|
||||
# link text contains an URL that has a different base than the actual URL
|
||||
attrs['_text'] = attrs[None, 'href']
|
||||
return attrs
|
||||
|
||||
|
||||
def abslink_callback(attrs, new=False):
|
||||
"""
|
||||
Makes sure that all links will be absolute links and will be opened in a new page with no
|
||||
window.opener attribute.
|
||||
"""
|
||||
url = attrs.get((None, 'href'), '/')
|
||||
if not url.startswith('mailto:') and not url.startswith('tel:'):
|
||||
attrs[None, 'href'] = urllib.parse.urljoin(settings.SITE_URL, url)
|
||||
@@ -133,7 +93,6 @@ def markdown_compile_email(source):
|
||||
linker = bleach.Linker(
|
||||
url_re=URL_RE,
|
||||
email_re=EMAIL_RE,
|
||||
callbacks=DEFAULT_CALLBACKS + [truelink_callback, abslink_callback],
|
||||
parse_email=True
|
||||
)
|
||||
return linker.linkify(bleach.clean(
|
||||
@@ -186,7 +145,7 @@ def rich_text(text: str, **kwargs):
|
||||
linker = bleach.Linker(
|
||||
url_re=URL_RE,
|
||||
email_re=EMAIL_RE,
|
||||
callbacks=DEFAULT_CALLBACKS + ([truelink_callback, safelink_callback] if kwargs.get('safelinks', True) else [truelink_callback, abslink_callback]),
|
||||
callbacks=DEFAULT_CALLBACKS + ([safelink_callback] if kwargs.get('safelinks', True) else [abslink_callback]),
|
||||
parse_email=True
|
||||
)
|
||||
body_md = linker.linkify(markdown_compile(text))
|
||||
@@ -202,7 +161,7 @@ def rich_text_snippet(text: str, **kwargs):
|
||||
linker = bleach.Linker(
|
||||
url_re=URL_RE,
|
||||
email_re=EMAIL_RE,
|
||||
callbacks=DEFAULT_CALLBACKS + ([truelink_callback, safelink_callback] if kwargs.get('safelinks', True) else [truelink_callback, abslink_callback]),
|
||||
callbacks=DEFAULT_CALLBACKS + ([safelink_callback] if kwargs.get('safelinks', True) else [abslink_callback]),
|
||||
parse_email=True
|
||||
)
|
||||
body_md = linker.linkify(markdown_compile(text, snippet=True))
|
||||
|
||||
@@ -13,11 +13,7 @@ class DownloadView(TemplateView):
|
||||
@cached_property
|
||||
def object(self) -> CachedFile:
|
||||
try:
|
||||
o = get_object_or_404(CachedFile, id=self.kwargs['id'], web_download=True)
|
||||
if o.session_key:
|
||||
if o.session_key != self.request.session.session_key:
|
||||
raise Http404()
|
||||
return o
|
||||
return get_object_or_404(CachedFile, id=self.kwargs['id'])
|
||||
except ValueError: # Invalid URLs
|
||||
raise Http404()
|
||||
|
||||
|
||||
@@ -203,7 +203,6 @@ class CachedFileField(ExtFileField):
|
||||
cf = CachedFile.objects.create(
|
||||
expires=now() + datetime.timedelta(days=1),
|
||||
date=now(),
|
||||
web_download=True,
|
||||
filename=data.name,
|
||||
type=data.content_type,
|
||||
)
|
||||
@@ -219,7 +218,6 @@ class CachedFileField(ExtFileField):
|
||||
if isinstance(data, File):
|
||||
cf = CachedFile.objects.create(
|
||||
expires=now() + datetime.timedelta(days=1),
|
||||
web_download=True,
|
||||
date=now(),
|
||||
filename=data.name,
|
||||
type=data.content_type,
|
||||
|
||||
@@ -3,15 +3,14 @@ from urllib.parse import urlencode, urlparse
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import RegexValidator, validate_email
|
||||
from django.core.validators import validate_email
|
||||
from django.db.models import Q
|
||||
from django.forms import formset_factory
|
||||
from django.forms import CheckboxSelectMultiple, formset_factory
|
||||
from django.urls import reverse
|
||||
from django.utils.html import escape
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.timezone import get_current_timezone_name
|
||||
from django.utils.translation import gettext, gettext_lazy as _, pgettext_lazy
|
||||
from django_countries import Countries
|
||||
from django_countries.fields import LazyTypedChoiceField
|
||||
from i18nfield.forms import (
|
||||
I18nForm, I18nFormField, I18nFormSetMixin, I18nTextarea, I18nTextInput,
|
||||
@@ -20,18 +19,21 @@ from pytz import common_timezones, timezone
|
||||
|
||||
from pretix.base.channels import get_all_sales_channels
|
||||
from pretix.base.email import get_available_placeholders
|
||||
from pretix.base.forms import I18nModelForm, PlaceholderValidator, SettingsForm
|
||||
from pretix.base.forms import (
|
||||
I18nModelForm, PlaceholderValidator, SettingsForm,
|
||||
)
|
||||
from pretix.base.models import Event, Organizer, TaxRule, Team
|
||||
from pretix.base.models.event import EventMetaValue, SubEvent
|
||||
from pretix.base.reldate import RelativeDateField, RelativeDateTimeField
|
||||
from pretix.base.settings import (
|
||||
PERSON_NAME_SCHEMES, PERSON_NAME_TITLE_GROUPS, validate_settings,
|
||||
PERSON_NAME_SCHEMES, PERSON_NAME_TITLE_GROUPS, validate_event_settings,
|
||||
)
|
||||
from pretix.control.forms import (
|
||||
ExtFileField, FontSelect, MultipleLanguagesWidget, SlugWidget,
|
||||
SplitDateTimeField, SplitDateTimePickerWidget,
|
||||
ExtFileField, MultipleLanguagesWidget, SlugWidget, SplitDateTimeField,
|
||||
SplitDateTimePickerWidget,
|
||||
)
|
||||
from pretix.control.forms.widgets import Select2
|
||||
from pretix.helpers.countries import CachedCountries
|
||||
from pretix.multidomain.models import KnownDomain
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.plugins.banktransfer.payment import BankTransfer
|
||||
@@ -311,6 +313,16 @@ class EventUpdateForm(I18nModelForm):
|
||||
required=False,
|
||||
help_text=_('You need to configure the custom domain in the webserver beforehand.')
|
||||
)
|
||||
self.fields['sales_channels'] = forms.MultipleChoiceField(
|
||||
label=self.fields['sales_channels'].label,
|
||||
help_text=self.fields['sales_channels'].help_text,
|
||||
required=self.fields['sales_channels'].required,
|
||||
initial=self.fields['sales_channels'].initial,
|
||||
choices=(
|
||||
(c.identifier, c.verbose_name) for c in get_all_sales_channels().values()
|
||||
),
|
||||
widget=forms.CheckboxSelectMultiple
|
||||
)
|
||||
|
||||
def clean_domain(self):
|
||||
d = self.cleaned_data['domain']
|
||||
@@ -367,6 +379,7 @@ class EventUpdateForm(I18nModelForm):
|
||||
'location',
|
||||
'geo_lat',
|
||||
'geo_lon',
|
||||
'sales_channels'
|
||||
]
|
||||
field_classes = {
|
||||
'date_from': SplitDateTimeField,
|
||||
@@ -381,6 +394,7 @@ class EventUpdateForm(I18nModelForm):
|
||||
'date_admission': SplitDateTimePickerWidget(attrs={'data-date-default': '#id_date_from_0'}),
|
||||
'presale_start': SplitDateTimePickerWidget(),
|
||||
'presale_end': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_presale_start_0'}),
|
||||
'sales_channels': CheckboxSelectMultiple()
|
||||
}
|
||||
|
||||
|
||||
@@ -431,57 +445,6 @@ class EventSettingsForm(SettingsForm):
|
||||
'WhatsApp and Reddit only show a square preview, so we recommend to make sure it still looks good '
|
||||
'only the center square is shown. If you do not fill this, we will use the logo given above.')
|
||||
)
|
||||
primary_color = forms.CharField(
|
||||
label=_("Primary color"),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
theme_color_success = forms.CharField(
|
||||
label=_("Accent color for success"),
|
||||
help_text=_("We strongly suggest to use a shade of green."),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
theme_color_danger = forms.CharField(
|
||||
label=_("Accent color for errors"),
|
||||
help_text=_("We strongly suggest to use a dark shade of red."),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
theme_color_background = forms.CharField(
|
||||
label=_("Page background color"),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield no-contrast'})
|
||||
)
|
||||
theme_round_borders = forms.BooleanField(
|
||||
label=_("Use round edges"),
|
||||
required=False,
|
||||
)
|
||||
primary_font = forms.ChoiceField(
|
||||
label=_('Font'),
|
||||
choices=[
|
||||
('Open Sans', 'Open Sans')
|
||||
],
|
||||
widget=FontSelect,
|
||||
help_text=_('Only respected by modern browsers.')
|
||||
)
|
||||
|
||||
auto_fields = [
|
||||
'imprint_url',
|
||||
@@ -518,18 +481,25 @@ class EventSettingsForm(SettingsForm):
|
||||
'attendee_company_required',
|
||||
'attendee_addresses_asked',
|
||||
'attendee_addresses_required',
|
||||
'attendee_data_explanation_text',
|
||||
'banner_text',
|
||||
'banner_text_bottom',
|
||||
'order_email_asked_twice',
|
||||
'last_order_modification_date',
|
||||
'checkout_show_copy_answers_button',
|
||||
'primary_color',
|
||||
'theme_color_success',
|
||||
'theme_color_danger',
|
||||
'theme_color_background',
|
||||
'theme_round_borders',
|
||||
'primary_font',
|
||||
]
|
||||
|
||||
def clean(self):
|
||||
data = super().clean()
|
||||
settings_dict = self.event.settings.freeze()
|
||||
settings_dict.update(data)
|
||||
validate_settings(self.event, data)
|
||||
validate_event_settings(self.event, data)
|
||||
return data
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -592,6 +562,7 @@ class PaymentSettingsForm(SettingsForm):
|
||||
'payment_term_last',
|
||||
'payment_term_expire_automatically',
|
||||
'payment_term_accept_late',
|
||||
'payment_pending_hidden',
|
||||
'payment_explanation',
|
||||
]
|
||||
tax_rate_default = forms.ModelChoiceField(
|
||||
@@ -618,7 +589,7 @@ class PaymentSettingsForm(SettingsForm):
|
||||
data = super().clean()
|
||||
settings_dict = self.obj.settings.freeze()
|
||||
settings_dict.update(data)
|
||||
validate_settings(self.obj, data)
|
||||
validate_event_settings(self.obj, data)
|
||||
return data
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -750,7 +721,7 @@ class InvoiceSettingsForm(SettingsForm):
|
||||
data = super().clean()
|
||||
settings_dict = self.obj.settings.freeze()
|
||||
settings_dict.update(data)
|
||||
validate_settings(self.obj, data)
|
||||
validate_event_settings(self.obj, data)
|
||||
return data
|
||||
|
||||
|
||||
@@ -1121,15 +1092,16 @@ class CommentForm(I18nModelForm):
|
||||
}
|
||||
|
||||
|
||||
class CountriesAndEU(Countries):
|
||||
class CountriesAndEU(CachedCountries):
|
||||
override = {
|
||||
'ZZ': _('Any country'),
|
||||
'EU': _('European Union')
|
||||
}
|
||||
first = ['ZZ', 'EU']
|
||||
cache_subkey = 'with_any_or_eu'
|
||||
|
||||
|
||||
class TaxRuleLineForm(forms.Form):
|
||||
class TaxRuleLineForm(I18nForm):
|
||||
country = LazyTypedChoiceField(
|
||||
choices=CountriesAndEU(),
|
||||
required=False
|
||||
@@ -1156,11 +1128,26 @@ class TaxRuleLineForm(forms.Form):
|
||||
max_digits=10, decimal_places=2,
|
||||
required=False
|
||||
)
|
||||
invoice_text = I18nFormField(
|
||||
label=_('Text on invoice'),
|
||||
required=False,
|
||||
widget=I18nTextInput
|
||||
)
|
||||
|
||||
|
||||
class I18nBaseFormSet(I18nFormSetMixin, forms.BaseFormSet):
|
||||
# compatibility shim for django-i18nfield library
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.event = kwargs.pop('event', None)
|
||||
if self.event:
|
||||
kwargs['locales'] = self.event.settings.get('locales')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
TaxRuleLineFormSet = formset_factory(
|
||||
TaxRuleLineForm,
|
||||
can_order=False, can_delete=True, extra=0
|
||||
TaxRuleLineForm, formset=I18nBaseFormSet,
|
||||
can_order=True, can_delete=True, extra=0
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -564,7 +564,7 @@ class EventOrderExpertFilterForm(EventOrderFilterForm):
|
||||
if fdata.get('created_from'):
|
||||
qs = qs.filter(datetime__gte=fdata.get('created_from'))
|
||||
if fdata.get('created_to'):
|
||||
qs = qs.filter(datetime__gte=fdata.get('created_to'))
|
||||
qs = qs.filter(datetime__lte=fdata.get('created_to'))
|
||||
if fdata.get('comment'):
|
||||
qs = qs.filter(comment__icontains=fdata.get('comment'))
|
||||
if fdata.get('sales_channel'):
|
||||
@@ -1113,8 +1113,8 @@ class CheckInFilterForm(FilterForm):
|
||||
'-item': ('-item__name', '-variation__value', '-order__code'),
|
||||
'seat': ('seat__sorting_rank', 'seat__guid'),
|
||||
'-seat': ('-seat__sorting_rank', '-seat__guid'),
|
||||
'date': ('subevent__date_from', 'order__code'),
|
||||
'-date': ('-subevent__date_from', '-order__code'),
|
||||
'date': ('subevent__date_from', 'subevent__id', 'order__code'),
|
||||
'-date': ('-subevent__date_from', 'subevent__id', '-order__code'),
|
||||
'name': {'_order': F('display_name').asc(nulls_first=True),
|
||||
'display_name': Coalesce('attendee_name_cached', 'addon_to__attendee_name_cached')},
|
||||
'-name': {'_order': F('display_name').desc(nulls_last=True),
|
||||
|
||||
@@ -41,6 +41,10 @@ class GlobalSettingsForm(SettingsForm):
|
||||
required=False,
|
||||
label=_("OpenCage API key for geocoding"),
|
||||
)),
|
||||
('mapquest_apikey', SecretKeySettingsField(
|
||||
required=False,
|
||||
label=_("MapQuest API key for geocoding"),
|
||||
)),
|
||||
('leaflet_tiles', forms.CharField(
|
||||
required=False,
|
||||
label=_("Leaflet tiles URL pattern"),
|
||||
|
||||
@@ -16,6 +16,7 @@ from i18nfield.forms import I18nFormField, I18nTextarea
|
||||
|
||||
from pretix.base.channels import get_all_sales_channels
|
||||
from pretix.base.forms import I18nFormSet, I18nModelForm
|
||||
from pretix.base.forms.widgets import DatePickerWidget
|
||||
from pretix.base.models import (
|
||||
Item, ItemCategory, ItemVariation, Question, QuestionOption, Quota,
|
||||
)
|
||||
@@ -111,14 +112,26 @@ class QuestionForm(I18nModelForm):
|
||||
'dependency_question',
|
||||
'dependency_values',
|
||||
'print_on_invoice',
|
||||
'valid_number_min',
|
||||
'valid_number_max',
|
||||
'valid_datetime_min',
|
||||
'valid_datetime_max',
|
||||
'valid_date_min',
|
||||
'valid_date_max',
|
||||
]
|
||||
widgets = {
|
||||
'valid_datetime_min': SplitDateTimePickerWidget(),
|
||||
'valid_datetime_max': SplitDateTimePickerWidget(),
|
||||
'valid_date_min': DatePickerWidget(),
|
||||
'valid_date_max': DatePickerWidget(),
|
||||
'items': forms.CheckboxSelectMultiple(
|
||||
attrs={'class': 'scrolling-multiple-choice'}
|
||||
),
|
||||
'dependency_values': forms.SelectMultiple,
|
||||
}
|
||||
field_classes = {
|
||||
'valid_datetime_min': SplitDateTimeField,
|
||||
'valid_datetime_max': SplitDateTimeField,
|
||||
'items': SafeModelMultipleChoiceField,
|
||||
'dependency_question': SafeModelChoiceField,
|
||||
}
|
||||
|
||||
@@ -4,24 +4,19 @@ from urllib.parse import urlparse
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import RegexValidator
|
||||
from django.db.models import Q
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
from django_scopes.forms import SafeModelMultipleChoiceField
|
||||
from i18nfield.forms import I18nFormField, I18nTextarea
|
||||
|
||||
from pretix.api.models import WebHook
|
||||
from pretix.api.webhooks import get_all_webhook_events
|
||||
from pretix.base.forms import I18nModelForm, SettingsForm
|
||||
from pretix.base.forms.widgets import SplitDateTimePickerWidget
|
||||
from pretix.base.models import Device, Gate, GiftCard, Organizer, Team
|
||||
from pretix.control.forms import (
|
||||
ExtFileField, FontSelect, MultipleLanguagesWidget, SplitDateTimeField,
|
||||
)
|
||||
from pretix.control.forms import ExtFileField, SplitDateTimeField
|
||||
from pretix.control.forms.event import SafeEventMultipleChoiceField
|
||||
from pretix.multidomain.models import KnownDomain
|
||||
from pretix.presale.style import get_fonts
|
||||
|
||||
|
||||
class OrganizerForm(I18nModelForm):
|
||||
@@ -218,72 +213,26 @@ class DeviceForm(forms.ModelForm):
|
||||
|
||||
|
||||
class OrganizerSettingsForm(SettingsForm):
|
||||
auto_fields = [
|
||||
'organizer_info_text',
|
||||
'event_list_type',
|
||||
'event_list_availability',
|
||||
'organizer_homepage_text',
|
||||
'organizer_link_back',
|
||||
'organizer_logo_image_large',
|
||||
'giftcard_length',
|
||||
'giftcard_expiry_years',
|
||||
'locales',
|
||||
'event_team_provisioning',
|
||||
'primary_color',
|
||||
'theme_color_success',
|
||||
'theme_color_danger',
|
||||
'theme_color_background',
|
||||
'theme_round_borders',
|
||||
'primary_font'
|
||||
|
||||
organizer_info_text = I18nFormField(
|
||||
label=_('Info text'),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
help_text=_('Not displayed anywhere by default, but if you want to, you can use this e.g. in ticket templates.')
|
||||
)
|
||||
]
|
||||
|
||||
event_team_provisioning = forms.BooleanField(
|
||||
label=_('Allow creating a new team during event creation'),
|
||||
help_text=_('Users that do not have access to all events under this organizer, must select one of their teams '
|
||||
'to have access to the created event. This setting allows users to create an event-specified team'
|
||||
' on-the-fly, even when they do not have \"Can change teams and permissions\" permission.'),
|
||||
required=False,
|
||||
)
|
||||
|
||||
primary_color = forms.CharField(
|
||||
label=_("Primary color"),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
theme_color_success = forms.CharField(
|
||||
label=_("Accent color for success"),
|
||||
help_text=_("We strongly suggest to use a shade of green."),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
theme_color_danger = forms.CharField(
|
||||
label=_("Accent color for errors"),
|
||||
help_text=_("We strongly suggest to use a shade of red."),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
theme_color_background = forms.CharField(
|
||||
label=_("Page background color"),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield no-contrast'})
|
||||
)
|
||||
theme_round_borders = forms.BooleanField(
|
||||
label=_("Use round edges"),
|
||||
required=False,
|
||||
)
|
||||
organizer_homepage_text = I18nFormField(
|
||||
label=_('Homepage text'),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
help_text=_('This will be displayed on the organizer homepage.')
|
||||
)
|
||||
organizer_logo_image = ExtFileField(
|
||||
label=_('Header image'),
|
||||
ext_whitelist=(".png", ".jpg", ".gif", ".jpeg"),
|
||||
@@ -294,44 +243,6 @@ class OrganizerSettingsForm(SettingsForm):
|
||||
'can increase the size with the setting below. We recommend not using small details on the picture '
|
||||
'as it will be resized on smaller screens.')
|
||||
)
|
||||
organizer_logo_image_large = forms.BooleanField(
|
||||
label=_('Use header image in its full size'),
|
||||
help_text=_('We recommend to upload a picture at least 1170 pixels wide.'),
|
||||
required=False,
|
||||
)
|
||||
event_list_type = forms.ChoiceField(
|
||||
label=_('Default overview style'),
|
||||
choices=(
|
||||
('list', _('List')),
|
||||
('week', _('Week calendar')),
|
||||
('calendar', _('Month calendar')),
|
||||
)
|
||||
)
|
||||
event_list_availability = forms.BooleanField(
|
||||
label=_('Show availability in event overviews'),
|
||||
help_text=_('If checked, the list of events will show if events are sold out. This might '
|
||||
'make for longer page loading times if you have lots of events and the shown status might be out '
|
||||
'of date for up to two minutes.'),
|
||||
required=False
|
||||
)
|
||||
organizer_link_back = forms.BooleanField(
|
||||
label=_('Link back to organizer overview on all event pages'),
|
||||
required=False
|
||||
)
|
||||
locales = forms.MultipleChoiceField(
|
||||
choices=settings.LANGUAGES,
|
||||
label=_("Use languages"),
|
||||
widget=MultipleLanguagesWidget,
|
||||
help_text=_('Choose all languages that your organizer homepage should be available in.')
|
||||
)
|
||||
primary_font = forms.ChoiceField(
|
||||
label=_('Font'),
|
||||
choices=[
|
||||
('Open Sans', 'Open Sans')
|
||||
],
|
||||
widget=FontSelect,
|
||||
help_text=_('Only respected by modern browsers.')
|
||||
)
|
||||
favicon = ExtFileField(
|
||||
label=_('Favicon'),
|
||||
ext_whitelist=(".ico", ".png", ".jpg", ".gif", ".jpeg"),
|
||||
@@ -340,24 +251,6 @@ class OrganizerSettingsForm(SettingsForm):
|
||||
help_text=_('If you provide a favicon, we will show it instead of the default pretix icon. '
|
||||
'We recommend a size of at least 200x200px to accommodate most devices.')
|
||||
)
|
||||
giftcard_length = forms.IntegerField(
|
||||
label=_('Length of gift card codes'),
|
||||
help_text=_('The system generates by default {}-character long gift card codes. However, if a different length '
|
||||
'is required, it can be set here.'.format(settings.ENTROPY['giftcard_secret'])),
|
||||
required=False
|
||||
)
|
||||
giftcard_expiry_years = forms.IntegerField(
|
||||
label=_('Validity of gift card codes in years'),
|
||||
help_text=_('If you set a number here, gift cards will by default expire at the end of the year after this '
|
||||
'many years. If you keep it empty, gift cards do not have an explicit expiry date.'),
|
||||
required=False
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['primary_font'].choices += [
|
||||
(a, {"title": a, "data": v}) for a, v in get_fonts().items()
|
||||
]
|
||||
|
||||
|
||||
class WebHookForm(forms.ModelForm):
|
||||
|
||||
@@ -305,6 +305,7 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
'pretix.event.order.email.attachments.skipped': _('The email has been sent without attachments since they '
|
||||
'would have been too large to be likely to arrive.'),
|
||||
'pretix.event.order.email.custom_sent': _('A custom email has been sent.'),
|
||||
'pretix.event.order.position.email.custom_sent': _('A custom email has been sent to an attendee.'),
|
||||
'pretix.event.order.email.download_reminder_sent': _('An email has been sent with a reminder that the ticket '
|
||||
'is available for download.'),
|
||||
'pretix.event.order.email.expire_warning_sent': _('An email has been sent with a warning that the order is about '
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
{% bootstrap_field form.invoice_address_beneficiary layout="control" %}
|
||||
{% bootstrap_field form.invoice_address_not_asked_free layout="control" %}
|
||||
{% bootstrap_field form.invoice_address_custom_field layout="control" %}
|
||||
{% bootstrap_field form.invoice_address_explanation_text layout="control" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Issuer details" %}</legend>
|
||||
@@ -51,7 +52,6 @@
|
||||
{% bootstrap_field form.invoice_additional_text layout="control" %}
|
||||
{% bootstrap_field form.invoice_footer_text layout="control" %}
|
||||
{% bootstrap_field form.invoice_logo_image layout="control" %}
|
||||
{% bootstrap_field form.invoice_address_explanation_text layout="control" %}
|
||||
{% bootstrap_field form.invoice_eu_currencies layout="control" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
{% bootstrap_field form.payment_term_last layout="control" %}
|
||||
{% bootstrap_field form.payment_term_expire_automatically layout="control" %}
|
||||
{% bootstrap_field form.payment_term_accept_late layout="control" %}
|
||||
{% bootstrap_field form.payment_pending_hidden layout="control" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Advanced" %}</legend>
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
{% bootstrap_field sform.attendee_addresses_asked layout="control" %}
|
||||
{% bootstrap_field sform.attendee_addresses_required layout="control" %}
|
||||
{% bootstrap_field sform.checkout_show_copy_answers_button layout="control" %}
|
||||
{% bootstrap_field sform.attendee_data_explanation_text layout="control" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Texts" %}</legend>
|
||||
@@ -219,6 +220,7 @@
|
||||
{% if sform.event_list_type %}
|
||||
{% bootstrap_field sform.event_list_type layout="control" %}
|
||||
{% endif %}
|
||||
{% bootstrap_field form.sales_channels layout="control" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Cart" %}</legend>
|
||||
|
||||
@@ -18,103 +18,135 @@
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
<div class="tabbed-form">
|
||||
<fieldset>
|
||||
<legend>{% trans "General" %}</legend>
|
||||
{% bootstrap_field form.name layout="control" %}
|
||||
{% bootstrap_field form.rate addon_after="%" layout="control" %}
|
||||
{% bootstrap_field form.price_includes_tax layout="control" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Advanced" %}</legend>
|
||||
<div class="alert alert-legal">
|
||||
{% blocktrans trimmed with docs="https://docs.pretix.eu/en/latest/user/events/taxes.html" %}
|
||||
These settings are intended for advanced users. See the
|
||||
<a href="{{ docs }}">documentation</a>
|
||||
for more information. Note that we are not responsible for the correct handling
|
||||
of taxes in your ticket shop. If in doubt, please contact a lawyer or tax consultant.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
{% bootstrap_field form.eu_reverse_charge layout="control" %}
|
||||
{% bootstrap_field form.home_country layout="control" %}
|
||||
<h3>{% trans "Custom taxation rules" %}</h3>
|
||||
<div class="alert alert-warning">
|
||||
{% blocktrans trimmed %}
|
||||
These settings are intended for professional users with very specific taxation situations.
|
||||
If you create any rule here, the reverse charge settings above will be ignored. The rules will be
|
||||
checked in order and once the first rule matches the order, it will be used and all further rules will
|
||||
be ignored. If no rule matches, tax will be charged.
|
||||
{% endblocktrans %}
|
||||
{% trans "All of these rules will only apply if an invoice address is set." %}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-lg-10">
|
||||
<div class="tabbed-form">
|
||||
<fieldset>
|
||||
<legend>{% trans "General" %}</legend>
|
||||
{% bootstrap_field form.name layout="control" %}
|
||||
{% bootstrap_field form.rate addon_after="%" layout="control" %}
|
||||
{% bootstrap_field form.price_includes_tax layout="control" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Advanced" %}</legend>
|
||||
<div class="alert alert-legal">
|
||||
{% blocktrans trimmed with docs="https://docs.pretix.eu/en/latest/user/events/taxes.html" %}
|
||||
These settings are intended for advanced users. See the
|
||||
<a href="{{ docs }}">documentation</a>
|
||||
for more information. Note that we are not responsible for the correct handling
|
||||
of taxes in your ticket shop. If in doubt, please contact a lawyer or tax consultant.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
{% bootstrap_field form.eu_reverse_charge layout="control" %}
|
||||
{% bootstrap_field form.home_country layout="control" %}
|
||||
<h3>{% trans "Custom taxation rules" %}</h3>
|
||||
<div class="alert alert-warning">
|
||||
{% blocktrans trimmed %}
|
||||
These settings are intended for professional users with very specific taxation situations.
|
||||
If you create any rule here, the reverse charge settings above will be ignored. The rules will be
|
||||
checked in order and once the first rule matches the order, it will be used and all further rules will
|
||||
be ignored. If no rule matches, tax will be charged.
|
||||
{% endblocktrans %}
|
||||
{% trans "All of these rules will only apply if an invoice address is set." %}
|
||||
</div>
|
||||
|
||||
<div class="formset" data-formset data-formset-prefix="{{ formset.prefix }}">
|
||||
{{ formset.management_form }}
|
||||
{% bootstrap_formset_errors formset %}
|
||||
<div data-formset-body>
|
||||
{% for form in formset %}
|
||||
{% bootstrap_form_errors form %}
|
||||
<div class="row" data-formset-form>
|
||||
<div class="sr-only">
|
||||
{{ form.id }}
|
||||
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
{% bootstrap_field form.country layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
{% bootstrap_field form.address_type layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
{% bootstrap_field form.action layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
{% bootstrap_field form.rate layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-1 text-right flip">
|
||||
<button type="button" class="btn btn-block btn-danger" data-formset-delete-button>
|
||||
<i class="fa fa-trash"></i></button>
|
||||
<div class="formset tax-rules-formset" data-formset data-formset-prefix="{{ formset.prefix }}">
|
||||
{{ formset.management_form }}
|
||||
{% bootstrap_formset_errors formset %}
|
||||
<script type="form-template" data-formset-empty-form>
|
||||
{% escapescript %}
|
||||
<div class="row tax-rule-line" data-formset-form>
|
||||
<div class="sr-only">
|
||||
{{ formset.empty_form.id }}
|
||||
{% bootstrap_field formset.empty_form.DELETE form_group_class="" layout="inline" %}
|
||||
{% bootstrap_field formset.empty_form.ORDER form_group_class="" layout="inline" %}
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-3 col-lg-3">
|
||||
{% bootstrap_field formset.empty_form.country layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-3 col-lg-4">
|
||||
{% bootstrap_field formset.empty_form.address_type layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-3 col-lg-3">
|
||||
{% bootstrap_field formset.empty_form.action layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-3 col-lg-2 text-right flip">
|
||||
<button type="button" class="btn btn-default" data-formset-move-up-button>
|
||||
<i class="fa fa-arrow-up"></i></button>
|
||||
<button type="button" class="btn btn-default" data-formset-move-down-button>
|
||||
<i class="fa fa-arrow-down"></i></button>
|
||||
<button type="button" class="btn btn-danger" data-formset-delete-button>
|
||||
<i class="fa fa-trash"></i></button>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-3 col-lg-4 col-md-offset-3">
|
||||
{% bootstrap_field formset.empty_form.invoice_text layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-3 col-lg-3">
|
||||
{% bootstrap_field formset.empty_form.rate layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
</div>
|
||||
{% endescapescript %}
|
||||
</script>
|
||||
<div data-formset-body class="tax-rule-lines">
|
||||
{% for form in formset %}
|
||||
{% bootstrap_form_errors form %}
|
||||
<div class="row tax-rule-line" data-formset-form>
|
||||
<div class="sr-only">
|
||||
{{ form.id }}
|
||||
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
|
||||
{% bootstrap_field form.ORDER form_group_class="" layout="inline" %}
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-3 col-lg-3">
|
||||
{% bootstrap_field form.country layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-3 col-lg-4">
|
||||
{% bootstrap_field form.address_type layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-3 col-lg-3">
|
||||
{% bootstrap_field form.action layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-3 col-lg-2 text-right flip">
|
||||
<button type="button" class="btn btn-default" data-formset-move-up-button>
|
||||
<i class="fa fa-arrow-up"></i></button>
|
||||
<button type="button" class="btn btn-default" data-formset-move-down-button>
|
||||
<i class="fa fa-arrow-down"></i></button>
|
||||
<button type="button" class="btn btn-danger" data-formset-delete-button>
|
||||
<i class="fa fa-trash"></i></button>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-3 col-lg-4 col-md-offset-3">
|
||||
{% bootstrap_field form.invoice_text layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-3 col-lg-3">
|
||||
{% bootstrap_field form.rate layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="row tax-rule-line" data-formset-form>
|
||||
<div class="col-sm-12">
|
||||
<button type="button" class="btn btn-default" data-formset-add>
|
||||
<i class="fa fa-plus"></i> {% trans "Add a new rule" %}</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<script type="form-template" data-formset-empty-form>
|
||||
{% escapescript %}
|
||||
<div class="row" data-formset-form>
|
||||
<div class="sr-only">
|
||||
{{ form.id }}
|
||||
{% bootstrap_field formset.empty_form.DELETE form_group_class="" layout="inline" %}
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
{% bootstrap_field formset.empty_form.country layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
{% bootstrap_field formset.empty_form.address_type layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
{% bootstrap_field formset.empty_form.action layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
{% bootstrap_field formset.empty_form.rate layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-sm-1 text-right flip">
|
||||
<button type="button" class="btn btn-block btn-danger" data-formset-delete-button>
|
||||
<i class="fa fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endescapescript %}
|
||||
</script>
|
||||
<p>
|
||||
<button type="button" class="btn btn-default" data-formset-add>
|
||||
<i class="fa fa-plus"></i> {% trans "Add a new rule" %}</button>
|
||||
</p>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="form-group submit-group">
|
||||
<button type="submit" class="btn btn-primary btn-save">
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
<div class="form-group submit-group">
|
||||
<button type="submit" class="btn btn-primary btn-save">
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-lg-2">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
{% trans "Change history" %}
|
||||
</h3>
|
||||
</div>
|
||||
{% include "pretixcontrol/includes/logs.html" with obj=rule %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</div>
|
||||
<div class="big-radio radio">
|
||||
<label>
|
||||
<input type="radio" value="on" name="{{ form.has_subevents.html_name }}" {% if not form.has_subevents.value %}checked{% endif %}>
|
||||
<input type="radio" value="on" name="{{ form.has_subevents.html_name }}" {% if form.has_subevents.avalue %}checked{% endif %}>
|
||||
<span class="fa fa-calendar"></span>
|
||||
<strong>{% trans "Event series or time slot booking" %}</strong>
|
||||
<div class="help-block">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
{% bootstrap_form form layout='horizontal' %}
|
||||
{% bootstrap_form form layout='control' %}
|
||||
<div class="form-group submit-group">
|
||||
<button type="submit" class="btn btn-primary btn-save">
|
||||
{% trans "Save" %}
|
||||
|
||||
@@ -32,6 +32,18 @@
|
||||
accepted. If you want to allow both options, do not make this field required.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
<div id="valid-number">
|
||||
{% bootstrap_field form.valid_number_min layout="control" %}
|
||||
{% bootstrap_field form.valid_number_max layout="control" %}
|
||||
</div>
|
||||
<div id="valid-date">
|
||||
{% bootstrap_field form.valid_date_min layout="control" %}
|
||||
{% bootstrap_field form.valid_date_max layout="control" %}
|
||||
</div>
|
||||
<div id="valid-datetime">
|
||||
{% bootstrap_field form.valid_datetime_min layout="control" %}
|
||||
{% bootstrap_field form.valid_datetime_max layout="control" %}
|
||||
</div>
|
||||
<div id="answer-options">
|
||||
<h3>{% trans "Answer options" %}</h3>
|
||||
<noscript>
|
||||
|
||||
@@ -74,15 +74,13 @@ def login(request):
|
||||
backend = [b for b in backends if b.visible][0]
|
||||
if request.user.is_authenticated:
|
||||
next_url = backend.get_next_url(request) or 'control:index'
|
||||
if next_url and url_has_allowed_host_and_scheme(next_url, allowed_hosts=None):
|
||||
return redirect(next_url)
|
||||
return redirect(reverse('control:index'))
|
||||
return redirect(next_url)
|
||||
if request.method == 'POST':
|
||||
form = LoginForm(backend=backend, data=request.POST, request=request)
|
||||
form = LoginForm(backend=backend, data=request.POST)
|
||||
if form.is_valid() and form.user_cache and form.user_cache.auth_backend == backend.identifier:
|
||||
return process_login(request, form.user_cache, form.cleaned_data.get('keep_logged_in', False))
|
||||
else:
|
||||
form = LoginForm(backend=backend, request=request)
|
||||
form = LoginForm(backend=backend)
|
||||
ctx['form'] = form
|
||||
ctx['can_register'] = settings.PRETIX_REGISTRATION
|
||||
ctx['can_reset'] = settings.PRETIX_PASSWORD_RESET
|
||||
|
||||
@@ -10,7 +10,6 @@ from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.files import File
|
||||
from django.core.serializers.json import DjangoJSONEncoder
|
||||
from django.db import transaction
|
||||
from django.db.models import ProtectedError
|
||||
from django.forms import inlineformset_factory
|
||||
@@ -28,6 +27,7 @@ from django.views.generic import DeleteView, FormView, ListView
|
||||
from django.views.generic.base import TemplateView, View
|
||||
from django.views.generic.detail import SingleObjectMixin
|
||||
from i18nfield.strings import LazyI18nString
|
||||
from i18nfield.utils import I18nJSONEncoder
|
||||
from pytz import timezone
|
||||
|
||||
from pretix.base.channels import get_all_sales_channels
|
||||
@@ -56,7 +56,7 @@ from pretix.plugins.stripe.payment import StripeSettingsHolder
|
||||
from pretix.presale.style import regenerate_css
|
||||
|
||||
from ...base.models.items import ItemMetaProperty
|
||||
from ...base.settings import LazyI18nStringList
|
||||
from ...base.settings import SETTINGS_AFFECTING_CSS, LazyI18nStringList
|
||||
from ..logdisplay import OVERVIEW_BANLIST
|
||||
from . import CreateView, PaginationMixin, UpdateView
|
||||
|
||||
@@ -161,11 +161,7 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
|
||||
if self.confirm_texts_formset.has_changed():
|
||||
data.update(confirm_texts=self.confirm_texts_formset.cleaned_data)
|
||||
self.request.event.log_action('pretix.event.settings', user=self.request.user, data=data)
|
||||
display_properties = (
|
||||
'primary_color', 'theme_color_success', 'theme_color_danger', 'primary_font',
|
||||
'theme_color_background', 'theme_round_borders',
|
||||
)
|
||||
if any(p in self.sform.changed_data for p in display_properties):
|
||||
if any(p in self.sform.changed_data for p in SETTINGS_AFFECTING_CSS):
|
||||
change_css = True
|
||||
if form.has_changed():
|
||||
self.request.event.log_action('pretix.event.changed', user=self.request.user, data={
|
||||
@@ -1097,6 +1093,7 @@ class TaxCreate(EventSettingsViewMixin, EventPermissionRequiredMixin, CreateView
|
||||
def formset(self):
|
||||
return TaxRuleLineFormSet(
|
||||
data=self.request.POST if self.request.method == "POST" else None,
|
||||
event=self.request.event,
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
@@ -1108,8 +1105,8 @@ class TaxCreate(EventSettingsViewMixin, EventPermissionRequiredMixin, CreateView
|
||||
def form_valid(self, form):
|
||||
form.instance.event = self.request.event
|
||||
form.instance.custom_rules = json.dumps([
|
||||
f.cleaned_data for f in self.formset if f not in self.formset.deleted_forms
|
||||
], cls=DjangoJSONEncoder)
|
||||
f.cleaned_data for f in self.formset.ordered_forms if f not in self.formset.deleted_forms
|
||||
], cls=I18nJSONEncoder)
|
||||
messages.success(self.request, _('The new tax rule has been created.'))
|
||||
ret = super().form_valid(form)
|
||||
form.instance.log_action('pretix.event.taxrule.added', user=self.request.user, data=dict(form.cleaned_data))
|
||||
@@ -1147,6 +1144,7 @@ class TaxUpdate(EventSettingsViewMixin, EventPermissionRequiredMixin, UpdateView
|
||||
def formset(self):
|
||||
return TaxRuleLineFormSet(
|
||||
data=self.request.POST if self.request.method == "POST" else None,
|
||||
event=self.request.event,
|
||||
initial=json.loads(self.object.custom_rules) if self.object.custom_rules else []
|
||||
)
|
||||
|
||||
@@ -1159,8 +1157,8 @@ class TaxUpdate(EventSettingsViewMixin, EventPermissionRequiredMixin, UpdateView
|
||||
def form_valid(self, form):
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
form.instance.custom_rules = json.dumps([
|
||||
f.cleaned_data for f in self.formset if f not in self.formset.deleted_forms
|
||||
], cls=DjangoJSONEncoder)
|
||||
f.cleaned_data for f in self.formset.ordered_forms if f not in self.formset.deleted_forms
|
||||
], cls=I18nJSONEncoder)
|
||||
if form.has_changed():
|
||||
self.object.log_action(
|
||||
'pretix.event.taxrule.changed', user=self.request.user, data={
|
||||
|
||||
@@ -14,14 +14,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class GeoCodeView(LoginRequiredMixin, View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
gs = GlobalSettingsObject()
|
||||
if not gs.settings.opencagedata_apikey:
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'results': []
|
||||
}, status=200)
|
||||
|
||||
q = request.GET.get('q')
|
||||
q = self.request.GET.get('q')
|
||||
cd = cache.get('geocode:{}'.format(q))
|
||||
if cd:
|
||||
return JsonResponse({
|
||||
@@ -29,6 +22,26 @@ class GeoCodeView(LoginRequiredMixin, View):
|
||||
'results': cd
|
||||
}, status=200)
|
||||
|
||||
gs = GlobalSettingsObject()
|
||||
if gs.settings.opencagedata_apikey:
|
||||
res = self._use_opencage(q)
|
||||
if gs.settings.mapquest_apikey:
|
||||
res = self._use_mapquest(q)
|
||||
else:
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'results': []
|
||||
}, status=200)
|
||||
|
||||
cache.set('geocode:{}'.format(q), res, timeout=3600 * 6)
|
||||
return JsonResponse({
|
||||
'success': True,
|
||||
'results': res
|
||||
}, status=200)
|
||||
|
||||
def _use_opencage(self, q):
|
||||
gs = GlobalSettingsObject()
|
||||
|
||||
try:
|
||||
r = requests.get(
|
||||
'https://api.opencagedata.com/geocode/v1/json?q={}&key={}'.format(
|
||||
@@ -51,9 +64,31 @@ class GeoCodeView(LoginRequiredMixin, View):
|
||||
'lon': r['geometry']['lng'],
|
||||
} for r in d['results']
|
||||
]
|
||||
cache.set('geocode:{}'.format(q), res, timeout=3600 * 6)
|
||||
return res
|
||||
|
||||
return JsonResponse({
|
||||
'success': True,
|
||||
'results': res
|
||||
}, status=200)
|
||||
def _use_mapquest(self, q):
|
||||
gs = GlobalSettingsObject()
|
||||
|
||||
try:
|
||||
r = requests.get(
|
||||
'http://www.mapquestapi.com/geocoding/v1/address?location={}&key={}'.format(
|
||||
quote(q), gs.settings.mapquest_apikey
|
||||
)
|
||||
)
|
||||
r.raise_for_status()
|
||||
except IOError:
|
||||
logger.exception("Geocoding failed")
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'results': []
|
||||
}, status=200)
|
||||
else:
|
||||
d = r.json()
|
||||
res = [
|
||||
{
|
||||
'formatted': q,
|
||||
'lat': r['locations'][0]['latLng']['lat'],
|
||||
'lon': r['locations'][0]['latLng']['lng'],
|
||||
} for r in d['results']
|
||||
]
|
||||
return res
|
||||
|
||||
@@ -1885,7 +1885,8 @@ class OrderEmailHistory(EventPermissionRequiredMixin, OrderViewMixin, ListView):
|
||||
)
|
||||
qs = order.all_logentries()
|
||||
qs = qs.filter(
|
||||
action_type__contains="order.email"
|
||||
Q(action_type__contains="order.email") |
|
||||
Q(action_type__contains="order.position.email")
|
||||
)
|
||||
return qs
|
||||
|
||||
@@ -2045,9 +2046,9 @@ class ExportDoView(EventPermissionRequiredMixin, ExportMixin, AsyncAction, View)
|
||||
messages.error(self.request, _('There was a problem processing your input. See below for error details.'))
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
cf = CachedFile(web_download=True, session_key=request.session.session_key)
|
||||
cf = CachedFile()
|
||||
cf.date = now()
|
||||
cf.expires = now() + timedelta(hours=24)
|
||||
cf.expires = now() + timedelta(days=3)
|
||||
cf.save()
|
||||
return self.do(self.request.event.id, str(cf.id), self.exporter.identifier, self.exporter.form.cleaned_data)
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ from pretix.base.models.organizer import TeamAPIToken
|
||||
from pretix.base.payment import PaymentException
|
||||
from pretix.base.services.export import multiexport
|
||||
from pretix.base.services.mail import SendMailException, mail
|
||||
from pretix.base.settings import SETTINGS_AFFECTING_CSS
|
||||
from pretix.base.signals import register_multievent_data_exporters
|
||||
from pretix.base.views.tasks import AsyncAction
|
||||
from pretix.control.forms.filter import (
|
||||
@@ -287,11 +288,7 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
|
||||
for k in self.sform.changed_data
|
||||
}
|
||||
)
|
||||
display_properties = (
|
||||
'primary_color', 'theme_color_success', 'theme_color_danger', 'primary_font',
|
||||
'theme_color_background', 'theme_round_borders'
|
||||
)
|
||||
if any(p in self.sform.changed_data for p in display_properties):
|
||||
if any(p in self.sform.changed_data for p in SETTINGS_AFFECTING_CSS):
|
||||
change_css = True
|
||||
if form.has_changed():
|
||||
self.request.organizer.log_action(
|
||||
@@ -1245,9 +1242,9 @@ class ExportDoView(OrganizerPermissionRequiredMixin, ExportMixin, AsyncAction, V
|
||||
messages.error(self.request, _('There was a problem processing your input. See below for error details.'))
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
cf = CachedFile(web_download=True, session_key=request.session.session_key)
|
||||
cf = CachedFile()
|
||||
cf.date = now()
|
||||
cf.expires = now() + timedelta(hours=24)
|
||||
cf.expires = now() + timedelta(days=3)
|
||||
cf.save()
|
||||
return self.do(
|
||||
organizer=self.request.organizer.id,
|
||||
|
||||
@@ -137,7 +137,7 @@ class BaseEditorView(EventPermissionRequiredMixin, TemplateView):
|
||||
buffer = BytesIO()
|
||||
p.write(buffer)
|
||||
buffer.seek(0)
|
||||
c = CachedFile(web_download=True)
|
||||
c = CachedFile()
|
||||
c.expires = now() + timedelta(days=7)
|
||||
c.date = now()
|
||||
c.filename = 'background_preview.pdf'
|
||||
@@ -162,7 +162,7 @@ class BaseEditorView(EventPermissionRequiredMixin, TemplateView):
|
||||
"status": "error",
|
||||
"error": error
|
||||
})
|
||||
c = CachedFile(web_download=True)
|
||||
c = CachedFile()
|
||||
c.expires = now() + timedelta(days=7)
|
||||
c.date = now()
|
||||
c.filename = 'background_preview.pdf'
|
||||
|
||||
@@ -75,7 +75,7 @@ class ShredExportView(RecentAuthenticationRequiredMixin, EventPermissionRequired
|
||||
if constr:
|
||||
return self.error(ShredError(self.get_error_url()))
|
||||
|
||||
return self.do(self.request.event.id, request.POST.getlist("shredder"), self.request.session.session_key)
|
||||
return self.do(self.request.event.id, request.POST.getlist("shredder"))
|
||||
|
||||
|
||||
class ShredDoView(RecentAuthenticationRequiredMixin, EventPermissionRequiredMixin, ShredderMixin, AsyncAction, View):
|
||||
|
||||
@@ -6,6 +6,7 @@ from django_countries.fields import CountryField
|
||||
|
||||
class CachedCountries(Countries):
|
||||
_cached_lists = {}
|
||||
cache_subkey = None
|
||||
|
||||
def __iter__(self):
|
||||
"""
|
||||
@@ -14,6 +15,8 @@ class CachedCountries(Countries):
|
||||
slow.
|
||||
"""
|
||||
cache_key = "countries:all:{}".format(get_language())
|
||||
if self.cache_subkey:
|
||||
cache_key += ":" + self.cache_subkey
|
||||
if cache_key in self._cached_lists:
|
||||
yield from self._cached_lists[cache_key]
|
||||
return
|
||||
|
||||
@@ -3,7 +3,7 @@ from io import BytesIO
|
||||
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.files.storage import default_storage
|
||||
from PIL import Image
|
||||
from PIL import Image, ImageOps
|
||||
from PIL.Image import LANCZOS
|
||||
|
||||
from pretix.helpers.models import Thumbnail
|
||||
@@ -56,6 +56,9 @@ def create_thumbnail(sourcename, size):
|
||||
except:
|
||||
raise ThumbnailError('Could not load image')
|
||||
|
||||
# before we calc thumbnail, we need to check and apply EXIF-orientation
|
||||
image = ImageOps.exif_transpose(image)
|
||||
|
||||
scale, crop = get_sizes(size, image.size)
|
||||
image = image.resize(scale, resample=LANCZOS)
|
||||
if crop:
|
||||
|
||||
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: 2020-11-24 09:10+0000\n"
|
||||
"POT-Creation-Date: 2020-11-27 17:32+0000\n"
|
||||
"PO-Revision-Date: 2020-07-30 19:00+0000\n"
|
||||
"Last-Translator: Abdullah <abdullah.gumaijan@gmail.com>\n"
|
||||
"Language-Team: Arabic <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -280,37 +280,37 @@ msgstr "توليد رسائل ..."
|
||||
msgid "Unknown error."
|
||||
msgstr "خطأ غير معروف."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:233
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "اللون لديه التباين الكبير وهو من السهل جدا أن تقرأ!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:237
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:245
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr "اللون لديه النقيض لائق وهو على الارجح جيدة بما فيه الكفاية لقراءة!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:249
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr "اللون لديه النقيض سيئة للنص على خلفية بيضاء، يرجى اختيار الظل أغمق."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:376
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:384
|
||||
msgid "All"
|
||||
msgstr "الكل"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:377
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:385
|
||||
msgid "None"
|
||||
msgstr "لا شيء"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:698
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:706
|
||||
msgid "Use a different name internally"
|
||||
msgstr "استخدام اسم مختلف داخليا"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:755
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:763
|
||||
msgid "Click to close"
|
||||
msgstr "انقر لقريب"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:770
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:778
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
@@ -326,15 +326,15 @@ msgstr "الآخرين"
|
||||
msgid "Count"
|
||||
msgstr "عد"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:131
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:135
|
||||
msgid "Yes"
|
||||
msgstr "نعم"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:132
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
msgid "No"
|
||||
msgstr "لا"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] ""
|
||||
@@ -362,34 +362,34 @@ msgstr[3] "سيتم إلغاء الحجز تلقائيا بعد {num} دقيقة
|
||||
msgstr[4] "سيتم إلغاء الحجز تلقائيا بعد {num} دقيقة."
|
||||
msgstr[5] "سيتم إلغاء الحجز تلقائيا بعد {num} دقيقة."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:260
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:268
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "الرجاء إدخال كمية التذاكر لأحد أنواع التذاكر."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:386
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "من٪ (العملة) ق٪ (سعر) ق"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:402
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "من٪ (العملة) ق٪ (سعر) ق"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:410
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:418
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:424
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:432
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:445
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:429
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
@@ -643,6 +643,33 @@ msgstr "شهر نوفمبر"
|
||||
msgid "December"
|
||||
msgstr "ديسمبر"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "May"
|
||||
#~ msgid "day"
|
||||
#~ msgstr "مايو"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "None"
|
||||
#~ msgid "on"
|
||||
#~ msgstr "لا شيء"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "months"
|
||||
#~ msgstr "الشهر القادم"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "month"
|
||||
#~ msgstr "الشهر القادم"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Others"
|
||||
#~ msgid "the"
|
||||
#~ msgstr "الآخرين"
|
||||
|
||||
#~ msgctxt "widget"
|
||||
#~ msgid ""
|
||||
#~ "<a href=\"https://pretix.eu\" target=\"_blank\" rel=\"noopener\">event "
|
||||
|
||||
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: 2020-11-24 09:10+0000\n"
|
||||
"POT-Creation-Date: 2020-11-27 17:32+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
@@ -257,37 +257,37 @@ msgstr ""
|
||||
msgid "Unknown error."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:233
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:237
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:245
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:249
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:376
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:384
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:377
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:385
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:698
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:706
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:755
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:763
|
||||
msgid "Click to close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:770
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:778
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
@@ -303,15 +303,15 @@ msgstr ""
|
||||
msgid "Count"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:131
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:135
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:132
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] ""
|
||||
@@ -331,28 +331,28 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:260
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:268
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:386
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:402
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:410
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:418
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:424
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:432
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:445
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:429
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
|
||||
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: 2020-11-24 09:10+0000\n"
|
||||
"POT-Creation-Date: 2020-11-27 17:32+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
@@ -257,37 +257,37 @@ msgstr ""
|
||||
msgid "Unknown error."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:233
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:237
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:245
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:249
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:376
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:384
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:377
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:385
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:698
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:706
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:755
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:763
|
||||
msgid "Click to close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:770
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:778
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
@@ -303,15 +303,15 @@ msgstr ""
|
||||
msgid "Count"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:131
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:135
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:132
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] ""
|
||||
@@ -333,28 +333,28 @@ msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:260
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:268
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:386
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:402
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:410
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:418
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:424
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:432
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:445
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:429
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
|
||||
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: 2020-11-24 09:10+0000\n"
|
||||
"POT-Creation-Date: 2020-11-27 17:32+0000\n"
|
||||
"PO-Revision-Date: 2020-09-15 02:00+0000\n"
|
||||
"Last-Translator: Mie Frydensbjerg <mif@aarhus.dk>\n"
|
||||
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -284,37 +284,37 @@ msgstr "Opretter beskeder …"
|
||||
msgid "Unknown error."
|
||||
msgstr "Ukendt fejl."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:233
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:237
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:245
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:249
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:376
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:384
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:377
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:385
|
||||
msgid "None"
|
||||
msgstr "Ingen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:698
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:706
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:755
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:763
|
||||
msgid "Click to close"
|
||||
msgstr "Klik for at lukke"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:770
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:778
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Du har ændringer, der ikke er gemt!"
|
||||
|
||||
@@ -332,17 +332,17 @@ msgstr "Andre"
|
||||
msgid "Count"
|
||||
msgstr "Antal"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:131
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:135
|
||||
msgid "Yes"
|
||||
msgstr "Ja"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:132
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
#, fuzzy
|
||||
#| msgid "None"
|
||||
msgid "No"
|
||||
msgstr "Ingen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] "(en dato mere)"
|
||||
@@ -362,34 +362,34 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] "Varerne i din kurv er reserveret for dig i et minut."
|
||||
msgstr[1] "Varerne i din kurv er reserveret for dig i {num} minutter."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:260
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:268
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:386
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "fra %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:402
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "fra %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:410
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:418
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:424
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:432
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:445
|
||||
msgid "Time zone:"
|
||||
msgstr "Tidszone:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:429
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
msgid "Your local time:"
|
||||
msgstr "Din lokaltid:"
|
||||
|
||||
@@ -643,6 +643,39 @@ msgstr "November"
|
||||
msgid "December"
|
||||
msgstr "December"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "May"
|
||||
#~ msgid "day"
|
||||
#~ msgstr "Maj"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next week"
|
||||
#~ msgid "week"
|
||||
#~ msgstr "Næste uge"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "None"
|
||||
#~ msgid "on"
|
||||
#~ msgstr "Ingen"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "months"
|
||||
#~ msgstr "Næste måned"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "month"
|
||||
#~ msgstr "Næste måned"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Others"
|
||||
#~ msgid "the"
|
||||
#~ msgstr "Andre"
|
||||
|
||||
#~ msgctxt "widget"
|
||||
#~ msgid ""
|
||||
#~ "<a href=\"https://pretix.eu\" target=\"_blank\" rel=\"noopener\">event "
|
||||
|
||||
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: 2020-11-24 09:10+0000\n"
|
||||
"POT-Creation-Date: 2020-11-27 17:32+0000\n"
|
||||
"PO-Revision-Date: 2020-08-25 02:00+0000\n"
|
||||
"Last-Translator: Dennis Lichtenthäler <lichtenthaeler@rami.io>\n"
|
||||
"Language-Team: German <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -276,16 +276,16 @@ msgstr "Generiere Nachrichten…"
|
||||
msgid "Unknown error."
|
||||
msgstr "Unbekannter Fehler."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:233
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
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:237
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:245
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Diese Farbe hat einen ausreichenden Kontrast und wahrscheinlich gut zu lesen!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:249
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -293,23 +293,23 @@ 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:376
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:384
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:377
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:385
|
||||
msgid "None"
|
||||
msgstr "Keine"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:698
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:706
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Intern einen anderen Namen verwenden"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:755
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:763
|
||||
msgid "Click to close"
|
||||
msgstr "Klicken zum Schließen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:770
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:778
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Sie haben ungespeicherte Änderungen!"
|
||||
|
||||
@@ -325,15 +325,15 @@ msgstr "Sonstige"
|
||||
msgid "Count"
|
||||
msgstr "Anzahl"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:131
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:135
|
||||
msgid "Yes"
|
||||
msgstr "Ja"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:132
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
msgid "No"
|
||||
msgstr "Nein"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] "(ein weiterer Termin)"
|
||||
@@ -355,28 +355,28 @@ msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
"Die Produkte in Ihrem Warenkorb sind noch {num} Minuten für Sie reserviert."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:260
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:268
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "Bitte tragen Sie eine Menge für eines der Produkte ein."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:386
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "Der Veranstalter behält %(currency)s %(amount)s ein"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:402
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "Sie erhalten %(currency)s %(amount)s zurück"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:410
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:418
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr "Bitte geben Sie den Betrag ein, den der Veranstalter einbehalten darf."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:424
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:432
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:445
|
||||
msgid "Time zone:"
|
||||
msgstr "Zeitzone:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:429
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
msgid "Your local time:"
|
||||
msgstr "Deine lokale Zeit:"
|
||||
|
||||
@@ -627,6 +627,44 @@ msgstr "November"
|
||||
msgid "December"
|
||||
msgstr "Dezember"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "May"
|
||||
#~ msgid "day"
|
||||
#~ msgstr "Mai"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Nein"
|
||||
#~ msgid "in"
|
||||
#~ msgstr "Nein"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next week"
|
||||
#~ msgid "week"
|
||||
#~ msgstr "Nächste Woche"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "None"
|
||||
#~ msgid "on"
|
||||
#~ msgstr "Keine"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "months"
|
||||
#~ msgstr "Nächster Monat"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "month"
|
||||
#~ msgstr "Nächster Monat"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Others"
|
||||
#~ msgid "the"
|
||||
#~ msgstr "Sonstige"
|
||||
|
||||
#~ msgctxt "widget"
|
||||
#~ msgid ""
|
||||
#~ "<a href=\"https://pretix.eu\" target=\"_blank\" rel=\"noopener\">event "
|
||||
@@ -638,9 +676,6 @@ msgstr "Dezember"
|
||||
#~ msgid "Ja"
|
||||
#~ msgstr "Ja"
|
||||
|
||||
#~ msgid "Nein"
|
||||
#~ msgstr "Nein"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Your request has been queued on the server and will now be processed. If "
|
||||
#~ "this takes longer than two minutes, please contact us or go back in your "
|
||||
|
||||
@@ -128,6 +128,7 @@ Leaflet
|
||||
loszulegen
|
||||
Ltd
|
||||
max
|
||||
MapQuest
|
||||
Merchandise
|
||||
Meta
|
||||
Metadaten
|
||||
|
||||
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: 2020-11-24 09:10+0000\n"
|
||||
"POT-Creation-Date: 2020-11-27 17:32+0000\n"
|
||||
"PO-Revision-Date: 2020-08-25 02:00+0000\n"
|
||||
"Last-Translator: Dennis Lichtenthäler <lichtenthaeler@rami.io>\n"
|
||||
"Language-Team: German (informal) <https://translate.pretix.eu/projects/"
|
||||
@@ -275,16 +275,16 @@ msgstr "Generiere Nachrichten…"
|
||||
msgid "Unknown error."
|
||||
msgstr "Unbekannter Fehler."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:233
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
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:237
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:245
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Diese Farbe hat einen ausreichenden Kontrast und wahrscheinlich gut zu lesen!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:249
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -292,23 +292,23 @@ 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:376
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:384
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:377
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:385
|
||||
msgid "None"
|
||||
msgstr "Keine"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:698
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:706
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Intern einen anderen Namen verwenden"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:755
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:763
|
||||
msgid "Click to close"
|
||||
msgstr "Klicken zum Schließen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:770
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:778
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Du hast ungespeicherte Änderungen!"
|
||||
|
||||
@@ -324,15 +324,15 @@ msgstr "Sonstige"
|
||||
msgid "Count"
|
||||
msgstr "Anzahl"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:131
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:135
|
||||
msgid "Yes"
|
||||
msgstr "Ja"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:132
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
msgid "No"
|
||||
msgstr "Nein"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] "(ein weiterer Termin)"
|
||||
@@ -354,28 +354,28 @@ msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
"Die Produkte in deinem Warenkorb sind noch {num} Minuten für dich reserviert."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:260
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:268
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "Bitte trage eine Menge für eines der Produkte ein."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:386
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "Der Veranstalter behält %(currency)s %(amount)s ein"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:402
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "Du erhältst %(currency)s %(amount)s zurück"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:410
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:418
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr "Bitte gib den Betrag ein, den der Veranstalter einbehalten darf."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:424
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:432
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:445
|
||||
msgid "Time zone:"
|
||||
msgstr "Zeitzone:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:429
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
msgid "Your local time:"
|
||||
msgstr "Deine lokale Zeit:"
|
||||
|
||||
@@ -626,6 +626,44 @@ msgstr "November"
|
||||
msgid "December"
|
||||
msgstr "Dezember"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "May"
|
||||
#~ msgid "day"
|
||||
#~ msgstr "Mai"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Nein"
|
||||
#~ msgid "in"
|
||||
#~ msgstr "Nein"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next week"
|
||||
#~ msgid "week"
|
||||
#~ msgstr "Nächste Woche"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "None"
|
||||
#~ msgid "on"
|
||||
#~ msgstr "Keine"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "months"
|
||||
#~ msgstr "Nächster Monat"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "month"
|
||||
#~ msgstr "Nächster Monat"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Others"
|
||||
#~ msgid "the"
|
||||
#~ msgstr "Sonstige"
|
||||
|
||||
#~ msgctxt "widget"
|
||||
#~ msgid ""
|
||||
#~ "<a href=\"https://pretix.eu\" target=\"_blank\" rel=\"noopener\">event "
|
||||
@@ -637,9 +675,6 @@ msgstr "Dezember"
|
||||
#~ msgid "Ja"
|
||||
#~ msgstr "Ja"
|
||||
|
||||
#~ msgid "Nein"
|
||||
#~ msgstr "Nein"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Your request has been queued on the server and will now be processed. If "
|
||||
#~ "this takes longer than two minutes, please contact us or go back in your "
|
||||
|
||||
@@ -128,6 +128,7 @@ Leaflet
|
||||
loszulegen
|
||||
Ltd
|
||||
max
|
||||
MapQuest
|
||||
Merchandise
|
||||
Meta
|
||||
Metadaten
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-11-24 09:10+0000\n"
|
||||
"POT-Creation-Date: 2020-11-27 17:32+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"
|
||||
@@ -258,37 +258,37 @@ msgstr ""
|
||||
msgid "Unknown error."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:233
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:237
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:245
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:249
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:376
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:384
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:377
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:385
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:698
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:706
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:755
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:763
|
||||
msgid "Click to close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:770
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:778
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
@@ -304,15 +304,15 @@ msgstr ""
|
||||
msgid "Count"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:131
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:135
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:132
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] ""
|
||||
@@ -332,28 +332,28 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:260
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:268
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:386
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:402
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:410
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:418
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:424
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:432
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:445
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:429
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
|
||||
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: 2020-11-24 09:10+0000\n"
|
||||
"POT-Creation-Date: 2020-11-27 17:32+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/"
|
||||
@@ -293,18 +293,18 @@ msgstr "Δημιουργία μηνυμάτων …"
|
||||
msgid "Unknown error."
|
||||
msgstr "Άγνωστο σφάλμα."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:233
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
"Το χρώμα σας έχει μεγάλη αντίθεση και είναι πολύ εύκολο να το διαβάσετε!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:237
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:245
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Το χρώμα σας έχει αξιοπρεπή αντίθεση και είναι ίσως αρκετά καλό για να "
|
||||
"διαβάσετε!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:249
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -312,23 +312,23 @@ msgstr ""
|
||||
"Το χρώμα σας έχει κακή αντίθεση για κείμενο σε λευκό φόντο, επιλέξτε μια πιο "
|
||||
"σκούρα σκιά."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:376
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:384
|
||||
msgid "All"
|
||||
msgstr "Όλα"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:377
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:385
|
||||
msgid "None"
|
||||
msgstr "Κανένας"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:698
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:706
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Χρησιμοποιήστε διαφορετικό όνομα εσωτερικά"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:755
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:763
|
||||
msgid "Click to close"
|
||||
msgstr "Κάντε κλικ για να κλείσετε"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:770
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:778
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
@@ -344,15 +344,15 @@ msgstr "Άλλοι"
|
||||
msgid "Count"
|
||||
msgstr "Λογαριασμός"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:131
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:135
|
||||
msgid "Yes"
|
||||
msgstr "Ναι"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:132
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
msgid "No"
|
||||
msgstr "Όχι"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] "(μία παραπάνω ημερομηνία)"
|
||||
@@ -372,34 +372,34 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] "Τα είδη στο καλάθι θα παραμείνουν δεσμευμένα για ένα λεπτό."
|
||||
msgstr[1] "Τα είδη στο καλάθι θα παραμείνουν δεσμευμένα για {num} λεπτά."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:260
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:268
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "Εισαγάγετε μια ποσότητα για έναν από τους τύπους εισιτηρίων."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:386
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "απο %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:402
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "απο %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:410
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:418
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:424
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:432
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:445
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:429
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
@@ -654,6 +654,33 @@ msgstr "Νοέμβριος"
|
||||
msgid "December"
|
||||
msgstr "Δεκέμβριος"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "May"
|
||||
#~ msgid "day"
|
||||
#~ msgstr "Μάιος"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "None"
|
||||
#~ msgid "on"
|
||||
#~ msgstr "Κανένας"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "months"
|
||||
#~ msgstr "Επόμενος μήνας"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "month"
|
||||
#~ msgstr "Επόμενος μήνας"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Others"
|
||||
#~ msgid "the"
|
||||
#~ msgstr "Άλλοι"
|
||||
|
||||
#~ msgctxt "widget"
|
||||
#~ msgid ""
|
||||
#~ "<a href=\"https://pretix.eu\" target=\"_blank\" rel=\"noopener\">event "
|
||||
|
||||
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: 2020-11-24 09:10+0000\n"
|
||||
"POT-Creation-Date: 2020-11-27 17:32+0000\n"
|
||||
"PO-Revision-Date: 2020-04-27 20:00+0000\n"
|
||||
"Last-Translator: Gonzalo Gabriel Perez <zalitoar@gmail.com>\n"
|
||||
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -289,17 +289,17 @@ msgstr "Generando mensajes…"
|
||||
msgid "Unknown error."
|
||||
msgstr "Error desconocido."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:233
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "¡Tu color tiene gran contraste y es muy legible!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:237
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:245
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"¡Tu color tiene un contraste decente y es probablemente suficientemente "
|
||||
"legible!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:249
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -307,23 +307,23 @@ 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:376
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:384
|
||||
msgid "All"
|
||||
msgstr "Todos"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:377
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:385
|
||||
msgid "None"
|
||||
msgstr "Ninguno"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:698
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:706
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Usar un nombre diferente internamente"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:755
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:763
|
||||
msgid "Click to close"
|
||||
msgstr "Click para cerrar"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:770
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:778
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "¡Tienes cambios sin guardar!"
|
||||
|
||||
@@ -339,15 +339,15 @@ msgstr "Otros"
|
||||
msgid "Count"
|
||||
msgstr "Cantidad"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:131
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:135
|
||||
msgid "Yes"
|
||||
msgstr "Si"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:132
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
msgid "No"
|
||||
msgstr "No"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] "(una fecha más)"
|
||||
@@ -369,34 +369,34 @@ msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
"Los elementos en su carrito de compras se han reservado por {num} minutos."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:260
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:268
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "Por favor, introduce un valor para cada tipo de entrada."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:386
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "a partir de %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:402
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "a partir de %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:410
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:418
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:424
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:432
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:445
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:429
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
@@ -652,6 +652,33 @@ msgstr "Noviembre"
|
||||
msgid "December"
|
||||
msgstr "Diciembre"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "May"
|
||||
#~ msgid "day"
|
||||
#~ msgstr "Mayo"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "None"
|
||||
#~ msgid "on"
|
||||
#~ msgstr "Ninguno"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "months"
|
||||
#~ msgstr "Siguiente mes"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "month"
|
||||
#~ msgstr "Siguiente mes"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Others"
|
||||
#~ msgid "the"
|
||||
#~ msgstr "Otros"
|
||||
|
||||
#~ msgctxt "widget"
|
||||
#~ msgid ""
|
||||
#~ "<a href=\"https://pretix.eu\" target=\"_blank\" rel=\"noopener\">event "
|
||||
|
||||
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: 2020-11-24 09:10+0000\n"
|
||||
"POT-Creation-Date: 2020-11-27 17:32+0000\n"
|
||||
"PO-Revision-Date: 2020-10-17 20:00+0000\n"
|
||||
"Last-Translator: Jaakko Rinta-Filppula <jaakko@r-f.fi>\n"
|
||||
"Language-Team: Finnish <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -261,37 +261,37 @@ msgstr ""
|
||||
msgid "Unknown error."
|
||||
msgstr "Tuntematon virhe."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:233
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:237
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:245
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:249
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:376
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:384
|
||||
msgid "All"
|
||||
msgstr "Kaikki"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:377
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:385
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:698
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:706
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Käytä toista nimeä sisäisesti"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:755
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:763
|
||||
msgid "Click to close"
|
||||
msgstr "Sulje klikkaamalla"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:770
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:778
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Sinulla on tallentamattomia muutoksia!"
|
||||
|
||||
@@ -307,15 +307,15 @@ msgstr "Muut"
|
||||
msgid "Count"
|
||||
msgstr "Määrä"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:131
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:135
|
||||
msgid "Yes"
|
||||
msgstr "Kyllä"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:132
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
msgid "No"
|
||||
msgstr "Ei"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] ""
|
||||
@@ -335,28 +335,28 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:260
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:268
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:386
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:402
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:410
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:418
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:424
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:432
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:445
|
||||
msgid "Time zone:"
|
||||
msgstr "Aikavyöhyke:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:429
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
@@ -604,3 +604,31 @@ msgstr "Marraskuu"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
msgid "December"
|
||||
msgstr "Joulukuu"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "May"
|
||||
#~ msgid "day"
|
||||
#~ msgstr "Toukokuu"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next week"
|
||||
#~ msgid "week"
|
||||
#~ msgstr "Seuraava viikko"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "months"
|
||||
#~ msgstr "Seuraava kuukausi"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "month"
|
||||
#~ msgstr "Seuraava kuukausi"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Others"
|
||||
#~ msgid "the"
|
||||
#~ msgstr "Muut"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: French\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-11-24 09:10+0000\n"
|
||||
"POT-Creation-Date: 2020-11-27 17:32+0000\n"
|
||||
"PO-Revision-Date: 2020-09-15 17:00+0000\n"
|
||||
"Last-Translator: Martin Gross <martin@pc-coholic.de>\n"
|
||||
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
@@ -287,17 +287,17 @@ msgstr "Création de messages …"
|
||||
msgid "Unknown error."
|
||||
msgstr "Erreur inconnue."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:233
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
"Votre choix de couleur est très facile à lire, il a un excellent contraste !"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:237
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:245
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Votre choix de couleur est assez bon pour la lecture et a un bon contraste !"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:249
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -305,23 +305,23 @@ msgstr ""
|
||||
"Votre choix de couleur n'a pas un bon contraste avec du texte sur un fond "
|
||||
"blanc, SVP choisissez un ton plus sombre."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:376
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:384
|
||||
msgid "All"
|
||||
msgstr "Tous"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:377
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:385
|
||||
msgid "None"
|
||||
msgstr "Aucun"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:698
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:706
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Utiliser un nom différent en interne"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:755
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:763
|
||||
msgid "Click to close"
|
||||
msgstr "Cliquez pour fermer"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:770
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:778
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Vous avez des modifications non sauvegardées !"
|
||||
|
||||
@@ -337,15 +337,15 @@ msgstr "Autres"
|
||||
msgid "Count"
|
||||
msgstr "Compter"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:131
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:135
|
||||
msgid "Yes"
|
||||
msgstr "Oui"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:132
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
msgid "No"
|
||||
msgstr "Non"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] "(une date en plus)"
|
||||
@@ -365,34 +365,34 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] "Les articles de votre panier vous sont réservés pour une minute."
|
||||
msgstr[1] "Les articles de votre panier vous sont réservés pour {num} minutes."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:260
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:268
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "SVP entrez une quantité pour un de vos types de billets."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:386
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "de %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:402
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "de %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:410
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:418
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:424
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:432
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:445
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:429
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
@@ -646,6 +646,33 @@ msgstr "Novembre"
|
||||
msgid "December"
|
||||
msgstr "Décembre"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "May"
|
||||
#~ msgid "day"
|
||||
#~ msgstr "Mai"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "None"
|
||||
#~ msgid "on"
|
||||
#~ msgstr "Aucun"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "months"
|
||||
#~ msgstr "Mois suivant"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "month"
|
||||
#~ msgstr "Mois suivant"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Others"
|
||||
#~ msgid "the"
|
||||
#~ msgstr "Autres"
|
||||
|
||||
#~ msgctxt "widget"
|
||||
#~ msgid ""
|
||||
#~ "<a href=\"https://pretix.eu\" target=\"_blank\" rel=\"noopener\">event "
|
||||
|
||||
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: 2020-11-24 09:10+0000\n"
|
||||
"POT-Creation-Date: 2020-11-27 17:32+0000\n"
|
||||
"PO-Revision-Date: 2020-01-24 08:00+0000\n"
|
||||
"Last-Translator: Prokaj Miklós <mixolid0@gmail.com>\n"
|
||||
"Language-Team: Hungarian <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -283,16 +283,16 @@ msgstr "Üzenetek generálása…"
|
||||
msgid "Unknown error."
|
||||
msgstr "Ismeretlen hiba."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:233
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "A választott színek remek kontrasztot adnak, és nagyon könnyű olvasni!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:237
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:245
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"A választott színek kontrasztja elégséges, és valószínűleg jól olvasható!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:249
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -300,23 +300,23 @@ msgstr ""
|
||||
"A választott színek kontrasztja elégtelen, kérjük válassz sötétebb "
|
||||
"árnyalatot."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:376
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:384
|
||||
msgid "All"
|
||||
msgstr "Összes"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:377
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:385
|
||||
msgid "None"
|
||||
msgstr "Semmi"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:698
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:706
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Használj másik nevet"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:755
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:763
|
||||
msgid "Click to close"
|
||||
msgstr "Bezárásért kattints"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:770
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:778
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Mentetlen változtatások!"
|
||||
|
||||
@@ -332,15 +332,15 @@ msgstr "Egyéb"
|
||||
msgid "Count"
|
||||
msgstr "Számítás"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:131
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:135
|
||||
msgid "Yes"
|
||||
msgstr "Igen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:132
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
msgid "No"
|
||||
msgstr "Nem"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] "(még egy időpont)"
|
||||
@@ -360,34 +360,34 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] "A kosár tartalma egy percig foglalva van számodra."
|
||||
msgstr[1] "A kosár tartalma {num} percig foglalva van számodra."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:260
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:268
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "Adjon meg egy mennyiséget az egyik jegytípusból."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:386
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "%(currency) %(price)-tól"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:402
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "%(currency) %(price)-tól"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:410
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:418
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:424
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:432
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:445
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:429
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
@@ -640,3 +640,30 @@ msgstr "November"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
msgid "December"
|
||||
msgstr "December"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "May"
|
||||
#~ msgid "day"
|
||||
#~ msgstr "Május"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "None"
|
||||
#~ msgid "on"
|
||||
#~ msgstr "Semmi"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "months"
|
||||
#~ msgstr "Következő hónap"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "month"
|
||||
#~ msgstr "Következő hónap"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Others"
|
||||
#~ msgid "the"
|
||||
#~ msgstr "Egyéb"
|
||||
|
||||
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: 2020-11-24 09:10+0000\n"
|
||||
"POT-Creation-Date: 2020-11-27 17:32+0000\n"
|
||||
"PO-Revision-Date: 2020-06-12 20:00+0000\n"
|
||||
"Last-Translator: Frank <webappconcept@gmail.com>\n"
|
||||
"Language-Team: Italian <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -283,39 +283,39 @@ msgstr "Stiamo generando i messaggi …"
|
||||
msgid "Unknown error."
|
||||
msgstr "Errore sconosciuto."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:233
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "Il colore scelto ha un ottimo contrasto ed è molto leggibile!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:237
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:245
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Il colore scelto ha un buon contrasto e probabilmente è abbastanza leggibile!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:249
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
"Il colore scelto non ha un buon contrasto, per favore scegline uno più scuro."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:376
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:384
|
||||
msgid "All"
|
||||
msgstr "Tutto"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:377
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:385
|
||||
msgid "None"
|
||||
msgstr "Nessuno"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:698
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:706
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Utilizza un nome diverso internamente"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:755
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:763
|
||||
msgid "Click to close"
|
||||
msgstr "Clicca per chiudere"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:770
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:778
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr "Hai cambiamenti non salvati!"
|
||||
|
||||
@@ -331,15 +331,15 @@ msgstr "Altri"
|
||||
msgid "Count"
|
||||
msgstr "Conteggio"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:131
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:135
|
||||
msgid "Yes"
|
||||
msgstr "Si"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:132
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
msgid "No"
|
||||
msgstr "No"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] "(un'altra data)"
|
||||
@@ -359,28 +359,28 @@ msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] "Gli elementi nel tuo carrello sono riservati per 1 minuto."
|
||||
msgstr[1] "Gli elementi nel tuo carrello sono riservati per {num} minuti."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:260
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:268
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "Inserisci la quantità per una tipologia di biglietto."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:386
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "L'organizzatore trattiene %(currency)s %(amount)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:402
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "Ricevi indietro %(currency)s %(amount)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:410
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:418
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr "Inserisci l'importo che l'organizzatore può trattenere."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:424
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:432
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:445
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:429
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
@@ -630,3 +630,36 @@ msgstr "Novembre"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:72
|
||||
msgid "December"
|
||||
msgstr "Dicembre"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "May"
|
||||
#~ msgid "day"
|
||||
#~ msgstr "Maggio"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next week"
|
||||
#~ msgid "week"
|
||||
#~ msgstr "Settimana successiva"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "None"
|
||||
#~ msgid "on"
|
||||
#~ msgstr "Nessuno"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "months"
|
||||
#~ msgstr "Mese successivo"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "month"
|
||||
#~ msgstr "Mese successivo"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Others"
|
||||
#~ msgid "the"
|
||||
#~ msgstr "Altri"
|
||||
|
||||
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: 2020-11-24 09:10+0000\n"
|
||||
"POT-Creation-Date: 2020-11-27 17:32+0000\n"
|
||||
"PO-Revision-Date: 2019-11-13 06:00+0000\n"
|
||||
"Last-Translator: Zane Smite <z.smite@riga-jurmala.com>\n"
|
||||
"Language-Team: Latvian <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
@@ -290,17 +290,17 @@ msgstr "Ziņas tiek ģenerētas …"
|
||||
msgid "Unknown error."
|
||||
msgstr "Nezināma kļūda."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:233
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr "Izvēlētā teksta krāsa ļoti labi izceļas un ir viegli lasāma!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:237
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:245
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
"Izvēlētā teksta krāsa pietiekami izceļas un visdrīzāk būs samērā viegli "
|
||||
"lasāma!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:241
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:249
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
@@ -308,23 +308,23 @@ msgstr ""
|
||||
"Izvēlētā krāsa tekstam neizceļas uz esošā fona, lūdzu, izvēlieties tumšāku "
|
||||
"krāsu."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:376
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:384
|
||||
msgid "All"
|
||||
msgstr "Visi"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:377
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:385
|
||||
msgid "None"
|
||||
msgstr "Neviens"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:698
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:706
|
||||
msgid "Use a different name internally"
|
||||
msgstr "Izmantojiet citu nosaukumu iekšēji"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:755
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:763
|
||||
msgid "Click to close"
|
||||
msgstr "Noklikšķiniet, lai aizvērtu"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:770
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:778
|
||||
msgid "You have unsaved changes!"
|
||||
msgstr ""
|
||||
|
||||
@@ -340,15 +340,15 @@ msgstr "Citi"
|
||||
msgid "Count"
|
||||
msgstr "Skaits"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:131
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:135
|
||||
msgid "Yes"
|
||||
msgstr "Jā"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:132
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
msgid "No"
|
||||
msgstr "Nē"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] "(neviens datums)"
|
||||
@@ -370,34 +370,34 @@ msgstr[0] "Preces jūsu grozā ir rezervētas nulle minūtes."
|
||||
msgstr[1] "Preces jūsu grozā ir rezervētas uz vienu minūti."
|
||||
msgstr[2] "Preces jūsu grozā ir rezervētas uz {num} minūtēm."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:260
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:268
|
||||
msgid "Please enter a quantity for one of the ticket types."
|
||||
msgstr "Lūdzu, ievadiet nepieciešamo daudzumu izvēlētajam biļešu veidam."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:386
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "no %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:394
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:402
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "from %(currency)s %(price)s"
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "no %(currency)s %(price)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:410
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:418
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:424
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:432
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:445
|
||||
msgid "Time zone:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:429
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:437
|
||||
msgid "Your local time:"
|
||||
msgstr ""
|
||||
|
||||
@@ -652,6 +652,33 @@ msgstr "Novembris"
|
||||
msgid "December"
|
||||
msgstr "Decembris"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "May"
|
||||
#~ msgid "day"
|
||||
#~ msgstr "Maijs"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "None"
|
||||
#~ msgid "on"
|
||||
#~ msgstr "Neviens"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "months"
|
||||
#~ msgstr "Nākamais mēnesis"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgctxt "widget"
|
||||
#~| msgid "Next month"
|
||||
#~ msgid "month"
|
||||
#~ msgstr "Nākamais mēnesis"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Others"
|
||||
#~ msgid "the"
|
||||
#~ msgstr "Citi"
|
||||
|
||||
#~ msgctxt "widget"
|
||||
#~ msgid ""
|
||||
#~ "<a href=\"https://pretix.eu\" target=\"_blank\" rel=\"noopener\">event "
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user