Merge pull request #4106 from ostcar/python-3.6-f-strings
use f-string syntax for strings
This commit is contained in:
commit
d5b09b4513
@ -26,7 +26,7 @@ def travis(args=None):
|
|||||||
with open(".travis.yml") as f:
|
with open(".travis.yml") as f:
|
||||||
travis = yaml.load(f)
|
travis = yaml.load(f)
|
||||||
for line in travis["script"]:
|
for line in travis["script"]:
|
||||||
print("Run: {}".format(line))
|
print(f"Run: {line}")
|
||||||
return_code = call(line)
|
return_code = call(line)
|
||||||
return_codes.append(return_code)
|
return_codes.append(return_code)
|
||||||
if return_code:
|
if return_code:
|
||||||
@ -62,7 +62,7 @@ def min_requirements(args=None):
|
|||||||
if req.specifier:
|
if req.specifier:
|
||||||
for spec, version in req.specs:
|
for spec, version in req.specs:
|
||||||
if spec == ">=":
|
if spec == ">=":
|
||||||
yield "{}=={}".format(req.name, version)
|
yield f"{req.name}=={version}"
|
||||||
|
|
||||||
print(" ".join(get_lowest_versions(args.requirements)))
|
print(" ".join(get_lowest_versions(args.requirements)))
|
||||||
|
|
||||||
|
@ -42,7 +42,8 @@ def main():
|
|||||||
else:
|
else:
|
||||||
# Check for unknown_args.
|
# Check for unknown_args.
|
||||||
if unknown_args:
|
if unknown_args:
|
||||||
parser.error("Unknown arguments {}".format(" ".join(unknown_args)))
|
joined_unknown_args = " ".join(unknown_args)
|
||||||
|
parser.error(f"Unknown arguments {joined_unknown_args}")
|
||||||
|
|
||||||
# Save arguments, if one wants to access them later.
|
# Save arguments, if one wants to access them later.
|
||||||
arguments.set_arguments(known_args)
|
arguments.set_arguments(known_args)
|
||||||
@ -239,7 +240,7 @@ def start(args):
|
|||||||
# Use flag --insecure to serve static files even if DEBUG is False.
|
# Use flag --insecure to serve static files even if DEBUG is False.
|
||||||
call_command(
|
call_command(
|
||||||
"runserver",
|
"runserver",
|
||||||
"{}:{}".format(args.host, args.port),
|
f"{args.host}:{args.port}",
|
||||||
noreload=False, # Means True, see above.
|
noreload=False, # Means True, see above.
|
||||||
insecure=True,
|
insecure=True,
|
||||||
)
|
)
|
||||||
@ -264,7 +265,7 @@ def createsettings(args):
|
|||||||
}
|
}
|
||||||
|
|
||||||
settings_path = write_settings(settings_dir, args.settings_filename, **context)
|
settings_path = write_settings(settings_dir, args.settings_filename, **context)
|
||||||
print("Settings created at %s" % settings_path)
|
print(f"Settings created at {settings_path}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -7,7 +7,6 @@ from django.contrib.contenttypes.fields import GenericForeignKey
|
|||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
|
||||||
|
|
||||||
from openslides.core.config import config
|
from openslides.core.config import config
|
||||||
from openslides.core.models import Countdown
|
from openslides.core.models import Countdown
|
||||||
@ -135,15 +134,13 @@ class ItemManager(models.Manager):
|
|||||||
for item_id, parent_id, weight in walk_items(tree):
|
for item_id, parent_id, weight in walk_items(tree):
|
||||||
# Check that the item is only once in the tree to prevent invalid trees
|
# Check that the item is only once in the tree to prevent invalid trees
|
||||||
if item_id in touched_items:
|
if item_id in touched_items:
|
||||||
raise ValueError(
|
raise ValueError(f"Item {item_id} is more then once in the tree.")
|
||||||
"Item {} is more then once in the tree.".format(item_id)
|
|
||||||
)
|
|
||||||
touched_items.add(item_id)
|
touched_items.add(item_id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
db_item = db_items[item_id]
|
db_item = db_items[item_id]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise ValueError("Item {} is not in the database.".format(item_id))
|
raise ValueError(f"Item {item_id} is not in the database.")
|
||||||
|
|
||||||
# Check if the item has changed and update it
|
# Check if the item has changed and update it
|
||||||
# Note: Do not use Item.objects.update, so that the items are sent
|
# Note: Do not use Item.objects.update, so that the items are sent
|
||||||
@ -171,10 +168,7 @@ class ItemManager(models.Manager):
|
|||||||
item_number = ".".join((number, item_number))
|
item_number = ".".join((number, item_number))
|
||||||
# Add prefix.
|
# Add prefix.
|
||||||
if config["agenda_number_prefix"]:
|
if config["agenda_number_prefix"]:
|
||||||
item_number_tmp = "%s %s" % (
|
item_number_tmp = f"{config['agenda_number_prefix']} {item_number}"
|
||||||
config["agenda_number_prefix"],
|
|
||||||
item_number,
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
item_number_tmp = item_number
|
item_number_tmp = item_number
|
||||||
# Save the new value and go down the tree.
|
# Save the new value and go down the tree.
|
||||||
@ -205,9 +199,9 @@ class Item(RESTModelMixin, models.Model):
|
|||||||
HIDDEN_ITEM = 3
|
HIDDEN_ITEM = 3
|
||||||
|
|
||||||
ITEM_TYPE = (
|
ITEM_TYPE = (
|
||||||
(AGENDA_ITEM, ugettext_lazy("Agenda item")),
|
(AGENDA_ITEM, "Agenda item"),
|
||||||
(INTERNAL_ITEM, ugettext_lazy("Internal item")),
|
(INTERNAL_ITEM, "Internal item"),
|
||||||
(HIDDEN_ITEM, ugettext_lazy("Hidden item")),
|
(HIDDEN_ITEM, "Hidden item"),
|
||||||
)
|
)
|
||||||
|
|
||||||
item_number = models.CharField(blank=True, max_length=255)
|
item_number = models.CharField(blank=True, max_length=255)
|
||||||
@ -362,13 +356,9 @@ class SpeakerManager(models.Manager):
|
|||||||
speakers). Cares also initial sorting of the coming speakers.
|
speakers). Cares also initial sorting of the coming speakers.
|
||||||
"""
|
"""
|
||||||
if self.filter(user=user, item=item, begin_time=None).exists():
|
if self.filter(user=user, item=item, begin_time=None).exists():
|
||||||
raise OpenSlidesError(
|
raise OpenSlidesError(f"{user} is already on the list of speakers.")
|
||||||
_("{user} is already on the list of speakers.").format(user=user)
|
|
||||||
)
|
|
||||||
if isinstance(user, AnonymousUser):
|
if isinstance(user, AnonymousUser):
|
||||||
raise OpenSlidesError(
|
raise OpenSlidesError("An anonymous user can not be on lists of speakers.")
|
||||||
_("An anonymous user can not be on lists of speakers.")
|
|
||||||
)
|
|
||||||
weight = (
|
weight = (
|
||||||
self.filter(item=item).aggregate(models.Max("weight"))["weight__max"] or 0
|
self.filter(item=item).aggregate(models.Max("weight"))["weight__max"] or 0
|
||||||
)
|
)
|
||||||
|
@ -51,16 +51,16 @@ def items(config: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
|||||||
show_tree = config.get("tree") or False
|
show_tree = config.get("tree") or False
|
||||||
|
|
||||||
if show_tree:
|
if show_tree:
|
||||||
items = get_tree(all_data, root_item_id or 0)
|
agenda_items = get_tree(all_data, root_item_id or 0)
|
||||||
else:
|
else:
|
||||||
items = []
|
agenda_items = []
|
||||||
for item in sorted(
|
for item in sorted(
|
||||||
all_data["agenda/item"].values(), key=lambda item: item["weight"]
|
all_data["agenda/item"].values(), key=lambda item: item["weight"]
|
||||||
):
|
):
|
||||||
if item["parent_id"] == root_item_id and item["type"] == 1:
|
if item["parent_id"] == root_item_id and item["type"] == 1:
|
||||||
items.append(item["title"])
|
agenda_items.append(item["title"])
|
||||||
|
|
||||||
return {"items": items}
|
return {"items": agenda_items}
|
||||||
|
|
||||||
|
|
||||||
def list_of_speakers(config: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
def list_of_speakers(config: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
||||||
@ -76,7 +76,7 @@ def list_of_speakers(config: Dict[str, Any], all_data: AllData) -> Dict[str, Any
|
|||||||
try:
|
try:
|
||||||
item = all_data["agenda/item"][item_id]
|
item = all_data["agenda/item"][item_id]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return {"error": "Item {} does not exist".format(item_id)}
|
return {"error": f"Item {item_id} does not exist"}
|
||||||
|
|
||||||
user_ids = []
|
user_ids = []
|
||||||
for speaker in item["speakers"]:
|
for speaker in item["speakers"]:
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import jsonschema
|
import jsonschema
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
|
|
||||||
from openslides.core.config import config
|
from openslides.core.config import config
|
||||||
from openslides.utils.autoupdate import inform_changed_data
|
from openslides.utils.autoupdate import inform_changed_data
|
||||||
@ -119,9 +118,7 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
if not has_perm(self.request.user, "agenda.can_be_speaker"):
|
if not has_perm(self.request.user, "agenda.can_be_speaker"):
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
if item.speaker_list_closed:
|
if item.speaker_list_closed:
|
||||||
raise ValidationError(
|
raise ValidationError({"detail": "The list of speakers is closed."})
|
||||||
{"detail": _("The list of speakers is closed.")}
|
|
||||||
)
|
|
||||||
user = self.request.user
|
user = self.request.user
|
||||||
else:
|
else:
|
||||||
# Add someone else.
|
# Add someone else.
|
||||||
@ -132,7 +129,7 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
try:
|
try:
|
||||||
user = get_user_model().objects.get(pk=int(user_id))
|
user = get_user_model().objects.get(pk=int(user_id))
|
||||||
except (ValueError, get_user_model().DoesNotExist):
|
except (ValueError, get_user_model().DoesNotExist):
|
||||||
raise ValidationError({"detail": _("User does not exist.")})
|
raise ValidationError({"detail": "User does not exist."})
|
||||||
|
|
||||||
# Try to add the user. This ensurse that a user is not twice in the
|
# Try to add the user. This ensurse that a user is not twice in the
|
||||||
# list of coming speakers.
|
# list of coming speakers.
|
||||||
@ -140,9 +137,6 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
Speaker.objects.add(user, item)
|
Speaker.objects.add(user, item)
|
||||||
except OpenSlidesError as e:
|
except OpenSlidesError as e:
|
||||||
raise ValidationError({"detail": str(e)})
|
raise ValidationError({"detail": str(e)})
|
||||||
message = (
|
|
||||||
_("User %s was successfully added to the list of speakers.") % user
|
|
||||||
)
|
|
||||||
|
|
||||||
# Send new speaker via autoupdate because users without permission
|
# Send new speaker via autoupdate because users without permission
|
||||||
# to see users may not have it but can get it now.
|
# to see users may not have it but can get it now.
|
||||||
@ -159,11 +153,11 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
try:
|
try:
|
||||||
user = get_user_model().objects.get(pk=int(user_id))
|
user = get_user_model().objects.get(pk=int(user_id))
|
||||||
except (ValueError, get_user_model().DoesNotExist):
|
except (ValueError, get_user_model().DoesNotExist):
|
||||||
raise ValidationError({"detail": _("User does not exist.")})
|
raise ValidationError({"detail": "User does not exist."})
|
||||||
|
|
||||||
marked = request.data.get("marked")
|
marked = request.data.get("marked")
|
||||||
if not isinstance(marked, bool):
|
if not isinstance(marked, bool):
|
||||||
raise ValidationError({"detail": _("Marked has to be a bool.")})
|
raise ValidationError({"detail": "Marked has to be a bool."})
|
||||||
|
|
||||||
queryset = Speaker.objects.filter(item=item, user=user)
|
queryset = Speaker.objects.filter(item=item, user=user)
|
||||||
try:
|
try:
|
||||||
@ -173,15 +167,11 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
speaker = queryset.get()
|
speaker = queryset.get()
|
||||||
except Speaker.DoesNotExist:
|
except Speaker.DoesNotExist:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("The user is not in the list of speakers.")}
|
{"detail": "The user is not in the list of speakers."}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
speaker.marked = marked
|
speaker.marked = marked
|
||||||
speaker.save()
|
speaker.save()
|
||||||
if speaker.marked:
|
|
||||||
message = _("You are successfully marked the speaker.")
|
|
||||||
else:
|
|
||||||
message = _("You are successfully unmarked the speaker.")
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# request.method == 'DELETE'
|
# request.method == 'DELETE'
|
||||||
@ -200,20 +190,17 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
speaker = queryset.get()
|
speaker = queryset.get()
|
||||||
except Speaker.DoesNotExist:
|
except Speaker.DoesNotExist:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("You are not on the list of speakers.")}
|
{"detail": "You are not on the list of speakers."}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
speaker.delete()
|
speaker.delete()
|
||||||
message = _(
|
|
||||||
"You are successfully removed from the list of speakers."
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
# Remove someone else.
|
# Remove someone else.
|
||||||
if not has_perm(
|
if not has_perm(
|
||||||
self.request.user, "agenda.can_manage_list_of_speakers"
|
self.request.user, "agenda.can_manage_list_of_speakers"
|
||||||
):
|
):
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
if type(speaker_ids) is int:
|
if isinstance(speaker_ids, int):
|
||||||
speaker_ids = [speaker_ids]
|
speaker_ids = [speaker_ids]
|
||||||
deleted_speaker_count = 0
|
deleted_speaker_count = 0
|
||||||
for speaker_id in speaker_ids:
|
for speaker_id in speaker_ids:
|
||||||
@ -223,29 +210,12 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
speaker.delete(skip_autoupdate=True)
|
speaker.delete(skip_autoupdate=True)
|
||||||
deleted_speaker_name = speaker
|
|
||||||
deleted_speaker_count += 1
|
deleted_speaker_count += 1
|
||||||
# send autoupdate if speakers are deleted
|
# send autoupdate if speakers are deleted
|
||||||
if deleted_speaker_count > 0:
|
if deleted_speaker_count:
|
||||||
inform_changed_data(item)
|
inform_changed_data(item)
|
||||||
|
|
||||||
if deleted_speaker_count > 1:
|
return Response()
|
||||||
message = (
|
|
||||||
str(deleted_speaker_count)
|
|
||||||
+ " "
|
|
||||||
+ _("speakers have been removed from the list of speakers.")
|
|
||||||
)
|
|
||||||
elif deleted_speaker_count == 1:
|
|
||||||
message = (
|
|
||||||
_("User %s has been removed from the list of speakers.")
|
|
||||||
% deleted_speaker_name
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
message = _(
|
|
||||||
"No speakers have been removed from the list of speakers."
|
|
||||||
)
|
|
||||||
# Initiate response.
|
|
||||||
return Response({"detail": message})
|
|
||||||
|
|
||||||
@detail_route(methods=["PUT", "DELETE"])
|
@detail_route(methods=["PUT", "DELETE"])
|
||||||
def speak(self, request, pk=None):
|
def speak(self, request, pk=None):
|
||||||
@ -263,16 +233,14 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
if speaker_id is None:
|
if speaker_id is None:
|
||||||
speaker = item.get_next_speaker()
|
speaker = item.get_next_speaker()
|
||||||
if speaker is None:
|
if speaker is None:
|
||||||
raise ValidationError(
|
raise ValidationError({"detail": "The list of speakers is empty."})
|
||||||
{"detail": _("The list of speakers is empty.")}
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
speaker = Speaker.objects.get(pk=int(speaker_id))
|
speaker = Speaker.objects.get(pk=int(speaker_id))
|
||||||
except (ValueError, Speaker.DoesNotExist):
|
except (ValueError, Speaker.DoesNotExist):
|
||||||
raise ValidationError({"detail": _("Speaker does not exist.")})
|
raise ValidationError({"detail": "Speaker does not exist."})
|
||||||
speaker.begin_speech()
|
speaker.begin_speech()
|
||||||
message = _("User is now speaking.")
|
message = "User is now speaking."
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# request.method == 'DELETE'
|
# request.method == 'DELETE'
|
||||||
@ -288,14 +256,11 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
except Speaker.DoesNotExist:
|
except Speaker.DoesNotExist:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{
|
||||||
"detail": _(
|
"detail": f"There is no one speaking at the moment according to {item}."
|
||||||
"There is no one speaking at the moment according to %(item)s."
|
|
||||||
)
|
|
||||||
% {"item": item}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
current_speaker.end_speech()
|
current_speaker.end_speech()
|
||||||
message = _("The speech is finished now.")
|
message = "The speech is finished now."
|
||||||
|
|
||||||
# Initiate response.
|
# Initiate response.
|
||||||
return Response({"detail": message})
|
return Response({"detail": message})
|
||||||
@ -313,7 +278,7 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
# Check data
|
# Check data
|
||||||
speaker_ids = request.data.get("speakers")
|
speaker_ids = request.data.get("speakers")
|
||||||
if not isinstance(speaker_ids, list):
|
if not isinstance(speaker_ids, list):
|
||||||
raise ValidationError({"detail": _("Invalid data.")})
|
raise ValidationError({"detail": "Invalid data."})
|
||||||
|
|
||||||
# Get all speakers
|
# Get all speakers
|
||||||
speakers = {}
|
speakers = {}
|
||||||
@ -324,7 +289,7 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
valid_speakers = []
|
valid_speakers = []
|
||||||
for speaker_id in speaker_ids:
|
for speaker_id in speaker_ids:
|
||||||
if not isinstance(speaker_id, int) or speakers.get(speaker_id) is None:
|
if not isinstance(speaker_id, int) or speakers.get(speaker_id) is None:
|
||||||
raise ValidationError({"detail": _("Invalid data.")})
|
raise ValidationError({"detail": "Invalid data."})
|
||||||
valid_speakers.append(speakers[speaker_id])
|
valid_speakers.append(speakers[speaker_id])
|
||||||
weight = 0
|
weight = 0
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
@ -337,7 +302,7 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
inform_changed_data(item)
|
inform_changed_data(item)
|
||||||
|
|
||||||
# Initiate response.
|
# Initiate response.
|
||||||
return Response({"detail": _("List of speakers successfully sorted.")})
|
return Response({"detail": "List of speakers successfully sorted."})
|
||||||
|
|
||||||
@list_route(methods=["post"])
|
@list_route(methods=["post"])
|
||||||
def numbering(self, request):
|
def numbering(self, request):
|
||||||
@ -347,11 +312,11 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
"""
|
"""
|
||||||
if not config["agenda_enable_numbering"]:
|
if not config["agenda_enable_numbering"]:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("Numbering of agenda items is deactivated.")}
|
{"detail": "Numbering of agenda items is deactivated."}
|
||||||
)
|
)
|
||||||
|
|
||||||
Item.objects.number_all(numeral_system=config["agenda_numeral_system"])
|
Item.objects.number_all(numeral_system=config["agenda_numeral_system"])
|
||||||
return Response({"detail": _("The agenda has been numbered.")})
|
return Response({"detail": "The agenda has been numbered."})
|
||||||
|
|
||||||
@list_route(methods=["post"])
|
@list_route(methods=["post"])
|
||||||
def sort(self, request):
|
def sort(self, request):
|
||||||
@ -377,15 +342,13 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
if ancestor == item:
|
if ancestor == item:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{
|
||||||
"detail": _(
|
"detail": "There must not be a hierarchical loop. Please reload the page."
|
||||||
"There must not be a hierarchical loop. Please reload the page."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
ancestor = ancestor.parent
|
ancestor = ancestor.parent
|
||||||
|
|
||||||
inform_changed_data(items)
|
inform_changed_data(items)
|
||||||
return Response({"detail": _("The agenda has been sorted.")})
|
return Response({"detail": "The agenda has been sorted."})
|
||||||
|
|
||||||
@list_route(methods=["post"])
|
@list_route(methods=["post"])
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
@ -429,11 +392,7 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
parent = Item.objects.get(pk=request.data["parent_id"])
|
parent = Item.objects.get(pk=request.data["parent_id"])
|
||||||
except Item.DoesNotExist:
|
except Item.DoesNotExist:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{"detail": f"Parent item {request.data['parent_id']} does not exist"}
|
||||||
"detail": "Parent item {} does not exist".format(
|
|
||||||
request.data["parent_id"]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Collect ancestors
|
# Collect ancestors
|
||||||
@ -450,9 +409,7 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
if item_id in ancestors:
|
if item_id in ancestors:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{
|
||||||
"detail": "Assigning item {} to one of its children is not possible.".format(
|
"detail": f"Assigning item {item_id} to one of its children is not possible."
|
||||||
item_id
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -460,9 +417,7 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
try:
|
try:
|
||||||
items.append(Item.objects.get(pk=item_id))
|
items.append(Item.objects.get(pk=item_id))
|
||||||
except Item.DoesNotExist:
|
except Item.DoesNotExist:
|
||||||
raise ValidationError(
|
raise ValidationError({"detail": f"Item {item_id} does not exist"})
|
||||||
{"detail": "Item {} does not exist".format(item_id)}
|
|
||||||
)
|
|
||||||
|
|
||||||
# OK, assign new parents.
|
# OK, assign new parents.
|
||||||
for item in items:
|
for item in items:
|
||||||
@ -474,10 +429,4 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
inform_changed_data(items)
|
inform_changed_data(items)
|
||||||
|
|
||||||
# Send response.
|
# Send response.
|
||||||
return Response(
|
return Response({"detail": f"{len(items)} items successfully assigned."})
|
||||||
{
|
|
||||||
"detail": _("{number} items successfully assigned.").format(
|
|
||||||
number=len(items)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
@ -6,7 +6,6 @@ from django.conf import settings
|
|||||||
from django.contrib.contenttypes.fields import GenericRelation
|
from django.contrib.contenttypes.fields import GenericRelation
|
||||||
from django.core.validators import MinValueValidator
|
from django.core.validators import MinValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext as _, ugettext_noop
|
|
||||||
|
|
||||||
from openslides.agenda.models import Item, Speaker
|
from openslides.agenda.models import Item, Speaker
|
||||||
from openslides.core.config import config
|
from openslides.core.config import config
|
||||||
@ -57,7 +56,7 @@ class AssignmentRelatedUser(RESTModelMixin, models.Model):
|
|||||||
unique_together = ("assignment", "user")
|
unique_together = ("assignment", "user")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s <-> %s" % (self.assignment, self.user)
|
return f"{self.assignment} <-> {self.user}"
|
||||||
|
|
||||||
def get_root_rest_element(self):
|
def get_root_rest_element(self):
|
||||||
"""
|
"""
|
||||||
@ -154,7 +153,7 @@ class Assignment(RESTModelMixin, models.Model):
|
|||||||
("can_manage", "Can manage elections"),
|
("can_manage", "Can manage elections"),
|
||||||
)
|
)
|
||||||
ordering = ("title",)
|
ordering = ("title",)
|
||||||
verbose_name = ugettext_noop("Election")
|
verbose_name = "Election"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.title
|
return self.title
|
||||||
@ -198,15 +197,13 @@ class Assignment(RESTModelMixin, models.Model):
|
|||||||
or 0
|
or 0
|
||||||
)
|
)
|
||||||
defaults = {"elected": False, "weight": weight + 1}
|
defaults = {"elected": False, "weight": weight + 1}
|
||||||
related_user, __ = self.assignment_related_users.update_or_create(
|
self.assignment_related_users.update_or_create(user=user, defaults=defaults)
|
||||||
user=user, defaults=defaults
|
|
||||||
)
|
|
||||||
|
|
||||||
def set_elected(self, user):
|
def set_elected(self, user):
|
||||||
"""
|
"""
|
||||||
Makes user an elected user for this assignment.
|
Makes user an elected user for this assignment.
|
||||||
"""
|
"""
|
||||||
related_user, __ = self.assignment_related_users.update_or_create(
|
self.assignment_related_users.update_or_create(
|
||||||
user=user, defaults={"elected": True}
|
user=user, defaults={"elected": True}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -224,7 +221,7 @@ class Assignment(RESTModelMixin, models.Model):
|
|||||||
Raises a ValueError if the phase is not valide.
|
Raises a ValueError if the phase is not valide.
|
||||||
"""
|
"""
|
||||||
if phase not in dict(self.PHASES):
|
if phase not in dict(self.PHASES):
|
||||||
raise ValueError("Invalid phase %s" % phase)
|
raise ValueError(f"Invalid phase {phase}")
|
||||||
|
|
||||||
self.phase = phase
|
self.phase = phase
|
||||||
|
|
||||||
@ -331,7 +328,7 @@ class Assignment(RESTModelMixin, models.Model):
|
|||||||
Return a title for the agenda with the appended assignment verbose name.
|
Return a title for the agenda with the appended assignment verbose name.
|
||||||
Note: It has to be the same return value like in JavaScript.
|
Note: It has to be the same return value like in JavaScript.
|
||||||
"""
|
"""
|
||||||
return "%s (%s)" % (self.get_agenda_title(), _(self._meta.verbose_name))
|
return f"{self.get_agenda_title()} (self._meta.verbose_name)"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def agenda_item(self):
|
def agenda_item(self):
|
||||||
@ -426,9 +423,8 @@ class AssignmentPoll( # type: ignore
|
|||||||
def get_vote_values(self):
|
def get_vote_values(self):
|
||||||
if self.pollmethod == "yna":
|
if self.pollmethod == "yna":
|
||||||
return ["Yes", "No", "Abstain"]
|
return ["Yes", "No", "Abstain"]
|
||||||
elif self.pollmethod == "yn":
|
if self.pollmethod == "yn":
|
||||||
return ["Yes", "No"]
|
return ["Yes", "No"]
|
||||||
else:
|
|
||||||
return ["Votes"]
|
return ["Votes"]
|
||||||
|
|
||||||
def get_ballot(self):
|
def get_ballot(self):
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
|
|
||||||
from openslides.poll.serializers import default_votes_validator
|
from openslides.poll.serializers import default_votes_validator
|
||||||
from openslides.utils.rest_api import (
|
from openslides.utils.rest_api import (
|
||||||
@ -30,7 +29,7 @@ def posts_validator(data):
|
|||||||
"""
|
"""
|
||||||
if data["open_posts"] and data["open_posts"] is not None and data["open_posts"] < 1:
|
if data["open_posts"] and data["open_posts"] is not None and data["open_posts"] < 1:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("Value for {} must be greater than 0").format("open_posts")}
|
{"detail": "Value for 'open_posts' must be greater than 0"}
|
||||||
)
|
)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@ -163,22 +162,20 @@ class AssignmentAllPollSerializer(ModelSerializer):
|
|||||||
if len(votes) != len(options):
|
if len(votes) != len(options):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{
|
||||||
"detail": _("You have to submit data for %d candidates.")
|
"detail": f"You have to submit data for {len(options)} candidates."
|
||||||
% len(options)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
for index, option in enumerate(options):
|
for index, option in enumerate(options):
|
||||||
if len(votes[index]) != len(instance.get_vote_values()):
|
if len(votes[index]) != len(instance.get_vote_values()):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{
|
||||||
"detail": _("You have to submit data for %d vote values.")
|
"detail": f"You have to submit data for {len(instance.get_vote_values())} vote values."
|
||||||
% len(instance.get_vote_values())
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
for vote_value, vote_weight in votes[index].items():
|
for vote_value, __ in votes[index].items():
|
||||||
if vote_value not in instance.get_vote_values():
|
if vote_value not in instance.get_vote_values():
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("Vote value %s is invalid.") % vote_value}
|
{"detail": f"Vote value {vote_value} is invalid."}
|
||||||
)
|
)
|
||||||
instance.set_vote_objects_with_values(
|
instance.set_vote_objects_with_values(
|
||||||
option, votes[index], skip_autoupdate=True
|
option, votes[index], skip_autoupdate=True
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
|
|
||||||
from openslides.utils.autoupdate import inform_changed_data
|
from openslides.utils.autoupdate import inform_changed_data
|
||||||
from openslides.utils.rest_api import (
|
from openslides.utils.rest_api import (
|
||||||
@ -75,7 +74,7 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
"""
|
"""
|
||||||
assignment = self.get_object()
|
assignment = self.get_object()
|
||||||
if assignment.is_elected(request.user):
|
if assignment.is_elected(request.user):
|
||||||
raise ValidationError({"detail": _("You are already elected.")})
|
raise ValidationError({"detail": "You are already elected."})
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
message = self.nominate_self(request, assignment)
|
message = self.nominate_self(request, assignment)
|
||||||
else:
|
else:
|
||||||
@ -87,9 +86,7 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
if assignment.phase == assignment.PHASE_FINISHED:
|
if assignment.phase == assignment.PHASE_FINISHED:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{
|
||||||
"detail": _(
|
"detail": "You can not candidate to this election because it is finished."
|
||||||
"You can not candidate to this election because it is finished."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if assignment.phase == assignment.PHASE_VOTING and not has_perm(
|
if assignment.phase == assignment.PHASE_VOTING and not has_perm(
|
||||||
@ -102,16 +99,14 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
# Send new candidate via autoupdate because users without permission
|
# Send new candidate via autoupdate because users without permission
|
||||||
# to see users may not have it but can get it now.
|
# to see users may not have it but can get it now.
|
||||||
inform_changed_data([request.user])
|
inform_changed_data([request.user])
|
||||||
return _("You were nominated successfully.")
|
return "You were nominated successfully."
|
||||||
|
|
||||||
def withdraw_self(self, request, assignment):
|
def withdraw_self(self, request, assignment):
|
||||||
# Withdraw candidature.
|
# Withdraw candidature.
|
||||||
if assignment.phase == assignment.PHASE_FINISHED:
|
if assignment.phase == assignment.PHASE_FINISHED:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{
|
||||||
"detail": _(
|
"detail": "You can not withdraw your candidature to this election because it is finished."
|
||||||
"You can not withdraw your candidature to this election because it is finished."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if assignment.phase == assignment.PHASE_VOTING and not has_perm(
|
if assignment.phase == assignment.PHASE_VOTING and not has_perm(
|
||||||
@ -121,10 +116,10 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
if not assignment.is_candidate(request.user):
|
if not assignment.is_candidate(request.user):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("You are not a candidate of this election.")}
|
{"detail": "You are not a candidate of this election."}
|
||||||
)
|
)
|
||||||
assignment.delete_related_user(request.user)
|
assignment.delete_related_user(request.user)
|
||||||
return _("You have withdrawn your candidature successfully.")
|
return "You have withdrawn your candidature successfully."
|
||||||
|
|
||||||
def get_user_from_request_data(self, request):
|
def get_user_from_request_data(self, request):
|
||||||
"""
|
"""
|
||||||
@ -133,22 +128,20 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
self.mark_elected can play with it.
|
self.mark_elected can play with it.
|
||||||
"""
|
"""
|
||||||
if not isinstance(request.data, dict):
|
if not isinstance(request.data, dict):
|
||||||
detail = _("Invalid data. Expected dictionary, got %s.") % type(
|
detail = f"Invalid data. Expected dictionary, got {type(request.data)}."
|
||||||
request.data
|
|
||||||
)
|
|
||||||
raise ValidationError({"detail": detail})
|
raise ValidationError({"detail": detail})
|
||||||
user_str = request.data.get("user", "")
|
user_str = request.data.get("user", "")
|
||||||
try:
|
try:
|
||||||
user_pk = int(user_str)
|
user_pk = int(user_str)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _('Invalid data. Expected something like {"user": <id>}.')}
|
{"detail": 'Invalid data. Expected something like {"user": <id>}.'}
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
user = get_user_model().objects.get(pk=user_pk)
|
user = get_user_model().objects.get(pk=user_pk)
|
||||||
except get_user_model().DoesNotExist:
|
except get_user_model().DoesNotExist:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("Invalid data. User %d does not exist.") % user_pk}
|
{"detail": f"Invalid data. User {user_pk} does not exist."}
|
||||||
)
|
)
|
||||||
return user
|
return user
|
||||||
|
|
||||||
@ -169,9 +162,9 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
|
|
||||||
def nominate_other(self, request, user, assignment):
|
def nominate_other(self, request, user, assignment):
|
||||||
if assignment.is_elected(user):
|
if assignment.is_elected(user):
|
||||||
raise ValidationError({"detail": _("User %s is already elected.") % user})
|
raise ValidationError({"detail": f"User {user} is already elected."})
|
||||||
if assignment.phase == assignment.PHASE_FINISHED:
|
if assignment.phase == assignment.PHASE_FINISHED:
|
||||||
detail = _(
|
detail = (
|
||||||
"You can not nominate someone to this election because it is finished."
|
"You can not nominate someone to this election because it is finished."
|
||||||
)
|
)
|
||||||
raise ValidationError({"detail": detail})
|
raise ValidationError({"detail": detail})
|
||||||
@ -181,28 +174,26 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
# To nominate another user during voting you have to be a manager.
|
# To nominate another user during voting you have to be a manager.
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
if assignment.is_candidate(user):
|
if assignment.is_candidate(user):
|
||||||
raise ValidationError({"detail": _("User %s is already nominated.") % user})
|
raise ValidationError({"detail": f"User {user} is already nominated."})
|
||||||
assignment.set_candidate(user)
|
assignment.set_candidate(user)
|
||||||
# Send new candidate via autoupdate because users without permission
|
# Send new candidate via autoupdate because users without permission
|
||||||
# to see users may not have it but can get it now.
|
# to see users may not have it but can get it now.
|
||||||
inform_changed_data(user)
|
inform_changed_data(user)
|
||||||
return _("User %s was nominated successfully.") % user
|
return f"User {user} was nominated successfully."
|
||||||
|
|
||||||
def delete_other(self, request, user, assignment):
|
def delete_other(self, request, user, assignment):
|
||||||
# To delete candidature status you have to be a manager.
|
# To delete candidature status you have to be a manager.
|
||||||
if not has_perm(request.user, "assignments.can_manage"):
|
if not has_perm(request.user, "assignments.can_manage"):
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
if assignment.phase == assignment.PHASE_FINISHED:
|
if assignment.phase == assignment.PHASE_FINISHED:
|
||||||
detail = _(
|
detail = "You can not delete someone's candidature to this election because it is finished."
|
||||||
"You can not delete someone's candidature to this election because it is finished."
|
|
||||||
)
|
|
||||||
raise ValidationError({"detail": detail})
|
raise ValidationError({"detail": detail})
|
||||||
if not assignment.is_candidate(user) and not assignment.is_elected(user):
|
if not assignment.is_candidate(user) and not assignment.is_elected(user):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("User %s has no status in this election.") % user}
|
{"detail": f"User {user} has no status in this election."}
|
||||||
)
|
)
|
||||||
assignment.delete_related_user(user)
|
assignment.delete_related_user(user)
|
||||||
return _("Candidate %s was withdrawn successfully.") % user
|
return f"Candidate {user} was withdrawn successfully."
|
||||||
|
|
||||||
@detail_route(methods=["post", "delete"])
|
@detail_route(methods=["post", "delete"])
|
||||||
def mark_elected(self, request, pk=None):
|
def mark_elected(self, request, pk=None):
|
||||||
@ -215,19 +206,17 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
if not assignment.is_candidate(user):
|
if not assignment.is_candidate(user):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("User %s is not a candidate of this election.") % user}
|
{"detail": f"User {user} is not a candidate of this election."}
|
||||||
)
|
)
|
||||||
assignment.set_elected(user)
|
assignment.set_elected(user)
|
||||||
message = _("User %s was successfully elected.") % user
|
message = f"User {user} was successfully elected."
|
||||||
else:
|
else:
|
||||||
# request.method == 'DELETE'
|
# request.method == 'DELETE'
|
||||||
if not assignment.is_elected(user):
|
if not assignment.is_elected(user):
|
||||||
detail = (
|
detail = f"User {user} is not an elected candidate of this election."
|
||||||
_("User %s is not an elected candidate of this election.") % user
|
|
||||||
)
|
|
||||||
raise ValidationError({"detail": detail})
|
raise ValidationError({"detail": detail})
|
||||||
assignment.set_candidate(user)
|
assignment.set_candidate(user)
|
||||||
message = _("User %s was successfully unelected.") % user
|
message = f"User {user} was successfully unelected."
|
||||||
return Response({"detail": message})
|
return Response({"detail": message})
|
||||||
|
|
||||||
@detail_route(methods=["post"])
|
@detail_route(methods=["post"])
|
||||||
@ -238,12 +227,12 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
assignment = self.get_object()
|
assignment = self.get_object()
|
||||||
if not assignment.candidates.exists():
|
if not assignment.candidates.exists():
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("Can not create ballot because there are no candidates.")}
|
{"detail": "Can not create ballot because there are no candidates."}
|
||||||
)
|
)
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
poll = assignment.create_poll()
|
poll = assignment.create_poll()
|
||||||
return Response(
|
return Response(
|
||||||
{"detail": _("Ballot created successfully."), "createdPollId": poll.pk}
|
{"detail": "Ballot created successfully.", "createdPollId": poll.pk}
|
||||||
)
|
)
|
||||||
|
|
||||||
@detail_route(methods=["post"])
|
@detail_route(methods=["post"])
|
||||||
@ -258,7 +247,7 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
# Check data
|
# Check data
|
||||||
related_user_ids = request.data.get("related_users")
|
related_user_ids = request.data.get("related_users")
|
||||||
if not isinstance(related_user_ids, list):
|
if not isinstance(related_user_ids, list):
|
||||||
raise ValidationError({"detail": _("users has to be a list of IDs.")})
|
raise ValidationError({"detail": "users has to be a list of IDs."})
|
||||||
|
|
||||||
# Get all related users from AssignmentRelatedUser.
|
# Get all related users from AssignmentRelatedUser.
|
||||||
related_users = {}
|
related_users = {}
|
||||||
@ -274,7 +263,7 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
not isinstance(related_user_id, int)
|
not isinstance(related_user_id, int)
|
||||||
or related_users.get(related_user_id) is None
|
or related_users.get(related_user_id) is None
|
||||||
):
|
):
|
||||||
raise ValidationError({"detail": _("Invalid data.")})
|
raise ValidationError({"detail": "Invalid data."})
|
||||||
valid_related_users.append(related_users[related_user_id])
|
valid_related_users.append(related_users[related_user_id])
|
||||||
|
|
||||||
# Sort the related users
|
# Sort the related users
|
||||||
@ -289,7 +278,7 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
inform_changed_data(assignment)
|
inform_changed_data(assignment)
|
||||||
|
|
||||||
# Initiate response.
|
# Initiate response.
|
||||||
return Response({"detail": _("Assignment related users successfully sorted.")})
|
return Response({"detail": "Assignment related users successfully sorted."})
|
||||||
|
|
||||||
|
|
||||||
class AssignmentPollViewSet(UpdateModelMixin, DestroyModelMixin, GenericViewSet):
|
class AssignmentPollViewSet(UpdateModelMixin, DestroyModelMixin, GenericViewSet):
|
||||||
|
@ -3,7 +3,6 @@ from typing import Any, Callable, Dict, Iterable, Optional, TypeVar, Union, cast
|
|||||||
from asgiref.sync import async_to_sync
|
from asgiref.sync import async_to_sync
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.core.exceptions import ValidationError as DjangoValidationError
|
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
from mypy_extensions import TypedDict
|
from mypy_extensions import TypedDict
|
||||||
|
|
||||||
from ..utils.cache import element_cache
|
from ..utils.cache import element_cache
|
||||||
@ -45,7 +44,7 @@ class ConfigHandler:
|
|||||||
Returns the value of the config variable.
|
Returns the value of the config variable.
|
||||||
"""
|
"""
|
||||||
if not self.exists(key):
|
if not self.exists(key):
|
||||||
raise ConfigNotFound(_("The config variable {} was not found.").format(key))
|
raise ConfigNotFound(f"The config variable {key} was not found.")
|
||||||
|
|
||||||
return async_to_sync(element_cache.get_element_full_data)(
|
return async_to_sync(element_cache.get_element_full_data)(
|
||||||
self.get_collection_string(), self.get_key_to_id()[key]
|
self.get_collection_string(), self.get_key_to_id()[key]
|
||||||
@ -95,7 +94,7 @@ class ConfigHandler:
|
|||||||
try:
|
try:
|
||||||
config_variable = self.config_variables[key]
|
config_variable = self.config_variables[key]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise ConfigNotFound(_("The config variable {} was not found.").format(key))
|
raise ConfigNotFound(f"The config variable {key} was not found.")
|
||||||
|
|
||||||
# Validate datatype and run validators.
|
# Validate datatype and run validators.
|
||||||
expected_type = INPUT_TYPE_MAPPING[config_variable.input_type]
|
expected_type = INPUT_TYPE_MAPPING[config_variable.input_type]
|
||||||
@ -105,8 +104,7 @@ class ConfigHandler:
|
|||||||
value = expected_type(value)
|
value = expected_type(value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ConfigError(
|
raise ConfigError(
|
||||||
_("Wrong datatype. Expected %(expected_type)s, got %(got_type)s.")
|
f"Wrong datatype. Expected {expected_type}, got {type(value)}."
|
||||||
% {"expected_type": expected_type, "got_type": type(value)}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if config_variable.input_type == "choice":
|
if config_variable.input_type == "choice":
|
||||||
@ -118,44 +116,38 @@ class ConfigHandler:
|
|||||||
if choices is None or value not in map(
|
if choices is None or value not in map(
|
||||||
lambda choice: choice["value"], choices
|
lambda choice: choice["value"], choices
|
||||||
):
|
):
|
||||||
raise ConfigError(_("Invalid input. Choice does not match."))
|
raise ConfigError("Invalid input. Choice does not match.")
|
||||||
|
|
||||||
for validator in config_variable.validators:
|
for validator in config_variable.validators:
|
||||||
try:
|
try:
|
||||||
validator(value)
|
validator(value)
|
||||||
except DjangoValidationError as e:
|
except DjangoValidationError as err:
|
||||||
raise ConfigError(e.messages[0])
|
raise ConfigError(err.messages[0])
|
||||||
|
|
||||||
if config_variable.input_type == "static":
|
if config_variable.input_type == "static":
|
||||||
if not isinstance(value, dict):
|
if not isinstance(value, dict):
|
||||||
raise ConfigError(_("This has to be a dict."))
|
raise ConfigError("This has to be a dict.")
|
||||||
whitelist = ("path", "display_name")
|
whitelist = ("path", "display_name")
|
||||||
for required_entry in whitelist:
|
for required_entry in whitelist:
|
||||||
if required_entry not in value:
|
if required_entry not in value:
|
||||||
raise ConfigError(_("{} has to be given.".format(required_entry)))
|
raise ConfigError(f"{required_entry} has to be given.")
|
||||||
if not isinstance(value[required_entry], str):
|
if not isinstance(value[required_entry], str):
|
||||||
raise ConfigError(
|
raise ConfigError(f"{required_entry} has to be a string.")
|
||||||
_("{} has to be a string.".format(required_entry))
|
|
||||||
)
|
|
||||||
|
|
||||||
if config_variable.input_type == "translations":
|
if config_variable.input_type == "translations":
|
||||||
if not isinstance(value, list):
|
if not isinstance(value, list):
|
||||||
raise ConfigError(_("Translations has to be a list."))
|
raise ConfigError("Translations has to be a list.")
|
||||||
for entry in value:
|
for entry in value:
|
||||||
if not isinstance(entry, dict):
|
if not isinstance(entry, dict):
|
||||||
raise ConfigError(
|
raise ConfigError(
|
||||||
_("Every value has to be a dict, not {}.".format(type(entry)))
|
f"Every value has to be a dict, not {type(entry)}."
|
||||||
)
|
)
|
||||||
whitelist = ("original", "translation")
|
whitelist = ("original", "translation")
|
||||||
for required_entry in whitelist:
|
for required_entry in whitelist:
|
||||||
if required_entry not in entry:
|
if required_entry not in entry:
|
||||||
raise ConfigError(
|
raise ConfigError(f"{required_entry} has to be given.")
|
||||||
_("{} has to be given.".format(required_entry))
|
|
||||||
)
|
|
||||||
if not isinstance(entry[required_entry], str):
|
if not isinstance(entry[required_entry], str):
|
||||||
raise ConfigError(
|
raise ConfigError(f"{required_entry} has to be a string.")
|
||||||
_("{} has to be a string.".format(required_entry))
|
|
||||||
)
|
|
||||||
|
|
||||||
# Save the new value to the database.
|
# Save the new value to the database.
|
||||||
db_value = ConfigStore.objects.get(key=key)
|
db_value = ConfigStore.objects.get(key=key)
|
||||||
@ -189,7 +181,7 @@ class ConfigHandler:
|
|||||||
intersection = set(item_index.keys()).intersection(self.config_variables.keys())
|
intersection = set(item_index.keys()).intersection(self.config_variables.keys())
|
||||||
if intersection:
|
if intersection:
|
||||||
raise ConfigError(
|
raise ConfigError(
|
||||||
_("Too many values for config variables {} found.").format(intersection)
|
f"Too many values for config variables {intersection} found."
|
||||||
)
|
)
|
||||||
|
|
||||||
self.config_variables.update(item_index)
|
self.config_variables.update(item_index)
|
||||||
@ -286,21 +278,17 @@ class ConfigVariable:
|
|||||||
on_change: OnChangeType = None,
|
on_change: OnChangeType = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
if input_type not in INPUT_TYPE_MAPPING:
|
if input_type not in INPUT_TYPE_MAPPING:
|
||||||
raise ValueError(_("Invalid value for config attribute input_type."))
|
raise ValueError("Invalid value for config attribute input_type.")
|
||||||
if input_type == "choice" and choices is None:
|
if input_type == "choice" and choices is None:
|
||||||
raise ConfigError(
|
raise ConfigError(
|
||||||
_(
|
|
||||||
"Either config attribute 'choices' must not be None or "
|
"Either config attribute 'choices' must not be None or "
|
||||||
"'input_type' must not be 'choice'."
|
"'input_type' must not be 'choice'."
|
||||||
)
|
)
|
||||||
)
|
|
||||||
elif input_type != "choice" and choices is not None:
|
elif input_type != "choice" and choices is not None:
|
||||||
raise ConfigError(
|
raise ConfigError(
|
||||||
_(
|
|
||||||
"Either config attribute 'choices' must be None or "
|
"Either config attribute 'choices' must be None or "
|
||||||
"'input_type' must be 'choice'."
|
"'input_type' must be 'choice'."
|
||||||
)
|
)
|
||||||
)
|
|
||||||
self.name = name
|
self.name = name
|
||||||
self.default_value = default_value
|
self.default_value = default_value
|
||||||
self.input_type = input_type
|
self.input_type = input_type
|
||||||
@ -309,7 +297,7 @@ class ConfigVariable:
|
|||||||
self.choices = choices
|
self.choices = choices
|
||||||
self.hidden = hidden
|
self.hidden = hidden
|
||||||
self.weight = weight
|
self.weight = weight
|
||||||
self.group = group or _("General")
|
self.group = group or "General"
|
||||||
self.subgroup = subgroup
|
self.subgroup = subgroup
|
||||||
self.validators = validators or ()
|
self.validators = validators or ()
|
||||||
self.on_change = on_change
|
self.on_change = on_change
|
||||||
|
@ -41,7 +41,7 @@ class Command(BaseCommand):
|
|||||||
if database_path:
|
if database_path:
|
||||||
do_backup(database_path, path)
|
do_backup(database_path, path)
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
"Database %s successfully stored at %s." % (database_path, path)
|
f"Database {database_path} successfully stored at {path}."
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise CommandError(
|
raise CommandError(
|
||||||
|
@ -28,8 +28,6 @@ class Command(BaseCommand):
|
|||||||
raise CommandError(str(e))
|
raise CommandError(str(e))
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
self.style.SUCCESS(
|
self.style.SUCCESS(
|
||||||
"Config {key} successfully changed to {value}.".format(
|
f"Config {options['key']} successfully changed to {config[options['key']]}."
|
||||||
key=options["key"], value=config[options["key"]]
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -32,12 +32,12 @@ def move_old_logo_settings(apps, schema_editor):
|
|||||||
|
|
||||||
for place in ("header", "footer"):
|
for place in ("header", "footer"):
|
||||||
try:
|
try:
|
||||||
logo_pdf = ConfigStore.objects.get(key="logo_pdf_{}".format(place))
|
logo_pdf = ConfigStore.objects.get(key=f"logo_pdf_{place}")
|
||||||
except ConfigStore.DoesNotExist:
|
except ConfigStore.DoesNotExist:
|
||||||
continue # The old entry is not in the database, nothing to change here
|
continue # The old entry is not in the database, nothing to change here
|
||||||
|
|
||||||
# The key of the new entry
|
# The key of the new entry
|
||||||
new_value_key = "logo_pdf_{}_L".format(place)
|
new_value_key = f"logo_pdf_{place}_L"
|
||||||
try:
|
try:
|
||||||
logo_pdf_L = ConfigStore.objects.get(key=new_value_key)
|
logo_pdf_L = ConfigStore.objects.get(key=new_value_key)
|
||||||
except ConfigStore.DoesNotExist:
|
except ConfigStore.DoesNotExist:
|
||||||
|
@ -199,7 +199,7 @@ class ChatMessage(RESTModelMixin, models.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Message {}".format(self.timestamp)
|
return f"Message {self.timestamp}"
|
||||||
|
|
||||||
|
|
||||||
class ProjectorMessage(RESTModelMixin, models.Model):
|
class ProjectorMessage(RESTModelMixin, models.Model):
|
||||||
@ -236,7 +236,7 @@ class Countdown(RESTModelMixin, models.Model):
|
|||||||
def control(self, action, skip_autoupdate=False):
|
def control(self, action, skip_autoupdate=False):
|
||||||
if action not in ("start", "stop", "reset"):
|
if action not in ("start", "stop", "reset"):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Action must be 'start', 'stop' or 'reset', not {}.".format(action)
|
f"Action must be 'start', 'stop' or 'reset', not {action}."
|
||||||
)
|
)
|
||||||
|
|
||||||
if action == "start":
|
if action == "start":
|
||||||
|
@ -27,7 +27,7 @@ def countdown(
|
|||||||
try:
|
try:
|
||||||
return all_data["core/countdown"][countdown_id]
|
return all_data["core/countdown"][countdown_id]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return {"error": "Countdown {} does not exist".format(countdown_id)}
|
return {"error": f"Countdown {countdown_id} does not exist"}
|
||||||
|
|
||||||
|
|
||||||
def message(
|
def message(
|
||||||
@ -48,7 +48,7 @@ def message(
|
|||||||
try:
|
try:
|
||||||
return all_data["core/projector-message"][message_id]
|
return all_data["core/projector-message"][message_id]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return {"error": "Message {} does not exist".format(message_id)}
|
return {"error": f"Message {message_id} does not exist"}
|
||||||
|
|
||||||
|
|
||||||
def register_projector_elements() -> None:
|
def register_projector_elements() -> None:
|
||||||
|
@ -9,7 +9,6 @@ from django.contrib.staticfiles.views import serve
|
|||||||
from django.db.models import F
|
from django.db.models import F
|
||||||
from django.http import Http404, HttpResponse
|
from django.http import Http404, HttpResponse
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
from django.views import static
|
from django.views import static
|
||||||
from django.views.generic.base import View
|
from django.views.generic.base import View
|
||||||
from mypy_extensions import TypedDict
|
from mypy_extensions import TypedDict
|
||||||
@ -204,10 +203,10 @@ class ProjectorViewSet(ModelViewSet):
|
|||||||
projector = self.get_object()
|
projector = self.get_object()
|
||||||
elements = request.data
|
elements = request.data
|
||||||
if not isinstance(elements, list):
|
if not isinstance(elements, list):
|
||||||
raise ValidationError({"detail": _("The data has to be a list.")})
|
raise ValidationError({"detail": "The data has to be a list."})
|
||||||
for element in elements:
|
for element in elements:
|
||||||
if not isinstance(element, dict):
|
if not isinstance(element, dict):
|
||||||
raise ValidationError({"detail": _("All elements have to be dicts.")})
|
raise ValidationError({"detail": "All elements have to be dicts."})
|
||||||
if element.get("name") is None:
|
if element.get("name") is None:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": "Invalid projector element. Name is missing."}
|
{"detail": "Invalid projector element. Name is missing."}
|
||||||
@ -361,41 +360,37 @@ class ProjectorViewSet(ModelViewSet):
|
|||||||
"""
|
"""
|
||||||
# The data has to be a dict.
|
# The data has to be a dict.
|
||||||
if not isinstance(request.data, dict):
|
if not isinstance(request.data, dict):
|
||||||
raise ValidationError({"detail": _("The data has to be a dict.")})
|
raise ValidationError({"detail": "The data has to be a dict."})
|
||||||
|
|
||||||
# Get projector ids to clear
|
# Get projector ids to clear
|
||||||
clear_projector_ids = request.data.get("clear_ids", [])
|
clear_projector_ids = request.data.get("clear_ids", [])
|
||||||
for id in clear_projector_ids:
|
for id in clear_projector_ids:
|
||||||
if not isinstance(id, int):
|
if not isinstance(id, int):
|
||||||
raise ValidationError(
|
raise ValidationError({"detail": f'The id "{id}" has to be int.'})
|
||||||
{"detail": _('The id "{}" has to be int.').format(id)}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Get the projector id and validate element to prune. This is optional.
|
# Get the projector id and validate element to prune. This is optional.
|
||||||
prune = request.data.get("prune")
|
prune = request.data.get("prune")
|
||||||
if prune is not None:
|
if prune is not None:
|
||||||
if not isinstance(prune, dict):
|
if not isinstance(prune, dict):
|
||||||
raise ValidationError({"detail": _("Prune has to be an object.")})
|
raise ValidationError({"detail": "Prune has to be an object."})
|
||||||
prune_projector_id = prune.get("id")
|
prune_projector_id = prune.get("id")
|
||||||
if not isinstance(prune_projector_id, int):
|
if not isinstance(prune_projector_id, int):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("The prune projector id has to be int.")}
|
{"detail": "The prune projector id has to be int."}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Get the projector after all clear operations, but check, if it exist.
|
# Get the projector after all clear operations, but check, if it exist.
|
||||||
if not Projector.objects.filter(pk=prune_projector_id).exists():
|
if not Projector.objects.filter(pk=prune_projector_id).exists():
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{
|
||||||
"detail": _('The projector with id "{}" does not exist').format(
|
"detail": f'The projector with id "{prune_projector_id}" does not exist'
|
||||||
prune_projector_id
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
prune_element = prune.get("element", {})
|
prune_element = prune.get("element", {})
|
||||||
if not isinstance(prune_element, dict):
|
if not isinstance(prune_element, dict):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("Prune element has to be a dict or not given.")}
|
{"detail": "Prune element has to be a dict or not given."}
|
||||||
)
|
)
|
||||||
if prune_element.get("name") is None:
|
if prune_element.get("name") is None:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
@ -457,9 +452,7 @@ class ProjectorViewSet(ModelViewSet):
|
|||||||
projector_instance.height = request.data["height"]
|
projector_instance.height = request.data["height"]
|
||||||
projector_instance.save()
|
projector_instance.save()
|
||||||
|
|
||||||
message = "Changing resolution to {width}x{height} was successful.".format(
|
message = f"Changing resolution to {request.data['width']}x{request.data['height']} was successful."
|
||||||
width=request.data["width"], height=request.data["height"]
|
|
||||||
)
|
|
||||||
return Response({"detail": message})
|
return Response({"detail": message})
|
||||||
|
|
||||||
@detail_route(methods=["post"])
|
@detail_route(methods=["post"])
|
||||||
@ -514,10 +507,9 @@ class ProjectorViewSet(ModelViewSet):
|
|||||||
projector_instance.save(skip_autoupdate=True)
|
projector_instance.save(skip_autoupdate=True)
|
||||||
projector_instance.refresh_from_db()
|
projector_instance.refresh_from_db()
|
||||||
inform_changed_data(projector_instance)
|
inform_changed_data(projector_instance)
|
||||||
message = "{action} {direction} was successful.".format(
|
action = (request.data["action"].capitalize(),)
|
||||||
action=request.data["action"].capitalize(),
|
direction = (request.data["direction"],)
|
||||||
direction=request.data["direction"],
|
message = f"{action} {direction} was successful."
|
||||||
)
|
|
||||||
return Response({"detail": message})
|
return Response({"detail": message})
|
||||||
|
|
||||||
@detail_route(methods=["post"])
|
@detail_route(methods=["post"])
|
||||||
@ -535,9 +527,7 @@ class ProjectorViewSet(ModelViewSet):
|
|||||||
projector_instance.scroll = request.data
|
projector_instance.scroll = request.data
|
||||||
|
|
||||||
projector_instance.save()
|
projector_instance.save()
|
||||||
message = "Setting scroll to {scroll} was successful.".format(
|
message = f"Setting scroll to {request.data} was successful."
|
||||||
scroll=request.data
|
|
||||||
)
|
|
||||||
return Response({"detail": message})
|
return Response({"detail": message})
|
||||||
|
|
||||||
@detail_route(methods=["post"])
|
@detail_route(methods=["post"])
|
||||||
@ -554,9 +544,7 @@ class ProjectorViewSet(ModelViewSet):
|
|||||||
projector_instance = self.get_object()
|
projector_instance = self.get_object()
|
||||||
projector_instance.blank = request.data
|
projector_instance.blank = request.data
|
||||||
projector_instance.save()
|
projector_instance.save()
|
||||||
message = "Setting 'blank' to {blank} was successful.".format(
|
message = f"Setting 'blank' to {request.data} was successful."
|
||||||
blank=request.data
|
|
||||||
)
|
|
||||||
return Response({"detail": message})
|
return Response({"detail": message})
|
||||||
|
|
||||||
@detail_route(methods=["post"])
|
@detail_route(methods=["post"])
|
||||||
@ -570,9 +558,7 @@ class ProjectorViewSet(ModelViewSet):
|
|||||||
"""
|
"""
|
||||||
if config["projector_broadcast"] == 0:
|
if config["projector_broadcast"] == 0:
|
||||||
config["projector_broadcast"] = pk
|
config["projector_broadcast"] = pk
|
||||||
message = "Setting projector {id} as broadcast projector was successful.".format(
|
message = f"Setting projector {pk} as broadcast projector was successful."
|
||||||
id=pk
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
config["projector_broadcast"] = 0
|
config["projector_broadcast"] = 0
|
||||||
message = "Disabling broadcast was successful."
|
message = "Disabling broadcast was successful."
|
||||||
@ -595,9 +581,7 @@ class ProjectorViewSet(ModelViewSet):
|
|||||||
except ProjectionDefault.DoesNotExist:
|
except ProjectionDefault.DoesNotExist:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{
|
||||||
"detail": "The projectiondefault with pk={pk} was not found.".format(
|
"detail": f"The projectiondefault with pk={request.data} was not found."
|
||||||
pk=request.data
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -606,9 +590,7 @@ class ProjectorViewSet(ModelViewSet):
|
|||||||
projectiondefault.save()
|
projectiondefault.save()
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
'Setting projectiondefault "{name}" to projector {projector_id} was successful.'.format(
|
f'Setting projectiondefault "{projectiondefault.display_name}" to projector {projector_instance.pk} was successful.'
|
||||||
name=projectiondefault.display_name, projector_id=projector_instance.pk
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -751,9 +733,9 @@ class ChatMessageViewSet(ModelViewSet):
|
|||||||
args.append((chatmessage.get_collection_string(), chatmessage.pk))
|
args.append((chatmessage.get_collection_string(), chatmessage.pk))
|
||||||
chatmessages.delete()
|
chatmessages.delete()
|
||||||
# Trigger autoupdate and setup response.
|
# Trigger autoupdate and setup response.
|
||||||
if len(args) > 0:
|
if args:
|
||||||
inform_deleted_data(args)
|
inform_deleted_data(args)
|
||||||
return Response({"detail": _("All chat messages deleted successfully.")})
|
return Response({"detail": "All chat messages deleted successfully."})
|
||||||
|
|
||||||
|
|
||||||
class ProjectorMessageViewSet(ModelViewSet):
|
class ProjectorMessageViewSet(ModelViewSet):
|
||||||
@ -838,7 +820,7 @@ class HistoryViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||||||
HistoryData.objects.all().delete()
|
HistoryData.objects.all().delete()
|
||||||
|
|
||||||
# Trigger autoupdate.
|
# Trigger autoupdate.
|
||||||
if len(args) > 0:
|
if args:
|
||||||
inform_deleted_data(args)
|
inform_deleted_data(args)
|
||||||
|
|
||||||
# Rebuild history.
|
# Rebuild history.
|
||||||
@ -846,7 +828,7 @@ class HistoryViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||||||
inform_changed_data(history_instances)
|
inform_changed_data(history_instances)
|
||||||
|
|
||||||
# Setup response.
|
# Setup response.
|
||||||
return Response({"detail": _("History was deleted successfully.")})
|
return Response({"detail": "History was deleted successfully."})
|
||||||
|
|
||||||
|
|
||||||
# Special API views
|
# Special API views
|
||||||
@ -920,7 +902,7 @@ class HistoryView(utils_views.APIView):
|
|||||||
self.permission_denied(self.request)
|
self.permission_denied(self.request)
|
||||||
try:
|
try:
|
||||||
timestamp = int(self.request.query_params.get("timestamp", 0))
|
timestamp = int(self.request.query_params.get("timestamp", 0))
|
||||||
except (ValueError):
|
except ValueError:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": "Invalid input. Timestamp should be an integer."}
|
{"detail": "Invalid input. Timestamp should be an integer."}
|
||||||
)
|
)
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
Instruction to update translations for OpenSlides (JavaScipt and Django):
|
|
||||||
-------------------------------------------------------------------------
|
|
||||||
|
|
||||||
1. Update English resource files:
|
|
||||||
|
|
||||||
a) for JavaScript run:
|
|
||||||
$ ./node_modules/.bin/gulp pot
|
|
||||||
-> updates 'openslides/locale/angular-gettext/template-en.pot'
|
|
||||||
|
|
||||||
b) for Django:
|
|
||||||
$ cd openslides
|
|
||||||
$ django-admin.py makemessages -l en
|
|
||||||
-> updates 'openslides/locale/en/LC_MESSAGES/django.po'
|
|
||||||
|
|
||||||
2. Commit and merge the following files into OpenSlides master repo:
|
|
||||||
a) openslides/locale/angular-gettext/template-en.pot
|
|
||||||
b) openslides/locale/en/LC_MESSAGES/django.po
|
|
||||||
|
|
||||||
Transifex will update both resource files once a day by pulling from GitHub.
|
|
||||||
|
|
||||||
3. Translate both files in transifex into desired languages.
|
|
||||||
https://www.transifex.com/openslides/
|
|
||||||
|
|
||||||
4. Download translated po files for each language and override it:
|
|
||||||
a) openslides/locale/angular-gettext/{LANG-CODE}.po
|
|
||||||
b) openslides/locale/{LANG-CODE}/LC_MESSAGES/django.po
|
|
||||||
|
|
||||||
5. Create mo file for each language (only for django po files required)
|
|
||||||
$ cd openslides
|
|
||||||
$ django-admin.py compilemessages
|
|
||||||
|
|
||||||
6. Commit and merge for each language the following files:
|
|
||||||
a) openslides/locale/angular-gettext/{LANG-CODE}.po
|
|
||||||
b) openslides/locale/{LANG-CODE}/LC_MESSAGES/django.po
|
|
||||||
openslides/locale/{LANG-CODE}/LC_MESSAGES/django.mo
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -1,677 +0,0 @@
|
|||||||
# Language file of OpenSlides used by Transifex:
|
|
||||||
# https://www.transifex.com/openslides/openslides/
|
|
||||||
# Copyright (C) 2011–2015 by OpenSlides team, see AUTHORS.
|
|
||||||
# This file is distributed under the same license as the OpenSlides package.
|
|
||||||
# Translators:
|
|
||||||
# emanuel <emanuel@intevation.de>, 2013
|
|
||||||
# Emanuel Schütze <emanuel.schuetze@intevation.de>, 2013
|
|
||||||
# fri, 2013
|
|
||||||
# Norman Jäckel <transifex16062013@normanjaeckel.de>, 2013-2014
|
|
||||||
# Oskar Hahn <mail@oshahn.de>, 2012
|
|
||||||
# fri, 2015-2017
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: OpenSlides\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2018-05-23 16:13+0200\n"
|
|
||||||
"PO-Revision-Date: 2018-05-23 14:15+0000\n"
|
|
||||||
"Last-Translator: Emanuel Schütze <emanuel.schuetze@intevation.de>\n"
|
|
||||||
"Language-Team: Czech (http://www.transifex.com/openslides/openslides/language/cs/)\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Language: cs\n"
|
|
||||||
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
|
|
||||||
|
|
||||||
#: agenda/models.py:206
|
|
||||||
msgid "Agenda item"
|
|
||||||
msgstr "Položka pořadu jednání"
|
|
||||||
|
|
||||||
#: agenda/models.py:207
|
|
||||||
msgid "Hidden item"
|
|
||||||
msgstr "Skrytá položka"
|
|
||||||
|
|
||||||
#: agenda/models.py:356
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{user} is already on the list of speakers."
|
|
||||||
msgstr "{user} je již na seznamu řečníků."
|
|
||||||
|
|
||||||
#: agenda/models.py:359
|
|
||||||
msgid "An anonymous user can not be on lists of speakers."
|
|
||||||
msgstr "Anonymní uživatel nemůže být v seznamu řečníků."
|
|
||||||
|
|
||||||
#: agenda/views.py:116
|
|
||||||
msgid "The list of speakers is closed."
|
|
||||||
msgstr "Seznam řečníků je uzavřen."
|
|
||||||
|
|
||||||
#: agenda/views.py:125 agenda/views.py:150
|
|
||||||
msgid "User does not exist."
|
|
||||||
msgstr "Uživatel neexistuje."
|
|
||||||
|
|
||||||
#: agenda/views.py:133
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully added to the list of speakers."
|
|
||||||
msgstr "Uživatel %s byl úspěšně přidán do seznamu řečníků."
|
|
||||||
|
|
||||||
#: agenda/views.py:154
|
|
||||||
msgid "Marked has to be a bool."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:163
|
|
||||||
msgid "The user is not in the list of speakers."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:168
|
|
||||||
msgid "You are successfully marked the speaker."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:170
|
|
||||||
msgid "You are successfully unmarked the speaker."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:187
|
|
||||||
msgid "You are not on the list of speakers."
|
|
||||||
msgstr "Nejste na seznamu řečníků."
|
|
||||||
|
|
||||||
#: agenda/views.py:190
|
|
||||||
msgid "You are successfully removed from the list of speakers."
|
|
||||||
msgstr "Jste úspěšně odstraněn ze seznamu řečníků."
|
|
||||||
|
|
||||||
#: agenda/views.py:212
|
|
||||||
msgid "speakers have been removed from the list of speakers."
|
|
||||||
msgstr "Řečníci byly úspěšně odstraněni ze seznamu řečníků."
|
|
||||||
|
|
||||||
#: agenda/views.py:214
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s has been removed from the list of speakers."
|
|
||||||
msgstr "Uživatel %s byl odstraněn ze seznamu řečníků."
|
|
||||||
|
|
||||||
#: agenda/views.py:216
|
|
||||||
msgid "No speakers have been removed from the list of speakers."
|
|
||||||
msgstr "Ze seznamu řečníků nebyli odstraněni žádní řečníci "
|
|
||||||
|
|
||||||
#: agenda/views.py:236
|
|
||||||
msgid "The list of speakers is empty."
|
|
||||||
msgstr "Seznam řečníků je prázdný."
|
|
||||||
|
|
||||||
#: agenda/views.py:241
|
|
||||||
msgid "Speaker does not exist."
|
|
||||||
msgstr "Řečník neexistuje."
|
|
||||||
|
|
||||||
#: agenda/views.py:243
|
|
||||||
msgid "User is now speaking."
|
|
||||||
msgstr "Uživatel nyní mluví."
|
|
||||||
|
|
||||||
#: agenda/views.py:254
|
|
||||||
#, python-format
|
|
||||||
msgid "There is no one speaking at the moment according to %(item)s."
|
|
||||||
msgstr "Nyní nemluví žádný řečník podle %(item)s."
|
|
||||||
|
|
||||||
#: agenda/views.py:256
|
|
||||||
msgid "The speech is finished now."
|
|
||||||
msgstr "Řeč je nyní skončena."
|
|
||||||
|
|
||||||
#: agenda/views.py:275 agenda/views.py:287 assignments/views.py:222
|
|
||||||
msgid "Invalid data."
|
|
||||||
msgstr "Neplatná data."
|
|
||||||
|
|
||||||
#: agenda/views.py:300
|
|
||||||
msgid "List of speakers successfully sorted."
|
|
||||||
msgstr "Seznam řečníků úspěšně roztříděn."
|
|
||||||
|
|
||||||
#: agenda/views.py:309
|
|
||||||
msgid "Numbering of agenda items is deactivated."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:312
|
|
||||||
msgid "The agenda has been numbered."
|
|
||||||
msgstr "Pořad jednání byl očíslován."
|
|
||||||
|
|
||||||
#: agenda/views.py:337
|
|
||||||
msgid "There must not be a hierarchical loop. Please reload the page."
|
|
||||||
msgstr "Nesmí být hierarchická smyčka. Nahrajte, prosím, stránku znovu."
|
|
||||||
|
|
||||||
#: agenda/views.py:341
|
|
||||||
msgid "The agenda has been sorted."
|
|
||||||
msgstr "Pořad jednání byl roztříděn."
|
|
||||||
|
|
||||||
#: assignments/models.py:164
|
|
||||||
msgid "Election"
|
|
||||||
msgstr "Volba"
|
|
||||||
|
|
||||||
#: assignments/serializers.py:31
|
|
||||||
msgid "Value for {} must be greater than 0"
|
|
||||||
msgstr "Hodnota pro {} nesmí být větší než 0"
|
|
||||||
|
|
||||||
#: assignments/serializers.py:149
|
|
||||||
#, python-format
|
|
||||||
msgid "You have to submit data for %d candidates."
|
|
||||||
msgstr "Musíte předat data pro %d uchazečů."
|
|
||||||
|
|
||||||
#: assignments/serializers.py:153 motions/serializers.py:236
|
|
||||||
#, python-format
|
|
||||||
msgid "You have to submit data for %d vote values."
|
|
||||||
msgstr "Musíte předat data pro %d voleb."
|
|
||||||
|
|
||||||
#: assignments/serializers.py:157 motions/serializers.py:240
|
|
||||||
#, python-format
|
|
||||||
msgid "Vote value %s is invalid."
|
|
||||||
msgstr "Hodnota pro volby %s je neplatná."
|
|
||||||
|
|
||||||
#: assignments/views.py:66
|
|
||||||
msgid "You are already elected."
|
|
||||||
msgstr "Již jste zvolen."
|
|
||||||
|
|
||||||
#: assignments/views.py:76
|
|
||||||
msgid "You can not candidate to this election because it is finished."
|
|
||||||
msgstr "Nemůžete se ucházet o zvolení v těchto volbách, protože tyto jsou již skončeny."
|
|
||||||
|
|
||||||
#: assignments/views.py:85
|
|
||||||
msgid "You were nominated successfully."
|
|
||||||
msgstr "Byl jste úspěšně navržen."
|
|
||||||
|
|
||||||
#: assignments/views.py:90
|
|
||||||
msgid ""
|
|
||||||
"You can not withdraw your candidature to this election because it is "
|
|
||||||
"finished."
|
|
||||||
msgstr "Nemůžete stáhnout své uchazečství o zvolení v těchto volbách, protože tyto jsou již skončeny."
|
|
||||||
|
|
||||||
#: assignments/views.py:95
|
|
||||||
msgid "You are not a candidate of this election."
|
|
||||||
msgstr "Nejste uchazeč/uchazečka pro tyto volby."
|
|
||||||
|
|
||||||
#: assignments/views.py:97
|
|
||||||
msgid "You have withdrawn your candidature successfully."
|
|
||||||
msgstr "Stáhl jste své uchazečství úspěšně."
|
|
||||||
|
|
||||||
#: assignments/views.py:106
|
|
||||||
#, python-format
|
|
||||||
msgid "Invalid data. Expected dictionary, got %s."
|
|
||||||
msgstr "Neplatná data. Očekáván diktovaný text, obdrženo %s."
|
|
||||||
|
|
||||||
#: assignments/views.py:112
|
|
||||||
msgid "Invalid data. Expected something like {\"user\": <id>}."
|
|
||||||
msgstr "Neplatná data. Očekáváno něco jako {\"user\": <id>}."
|
|
||||||
|
|
||||||
#: assignments/views.py:116
|
|
||||||
#, python-format
|
|
||||||
msgid "Invalid data. User %d does not exist."
|
|
||||||
msgstr "Neplatná data. Uživatel %d neexistuje."
|
|
||||||
|
|
||||||
#: assignments/views.py:136
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is already elected."
|
|
||||||
msgstr "Uživatel %s je již zvolen."
|
|
||||||
|
|
||||||
#: assignments/views.py:138
|
|
||||||
msgid "You can not nominate someone to this election because it is finished."
|
|
||||||
msgstr "Nemůžete někoho jmenovat do těchto voleb, protože tyto jsou již skončeny."
|
|
||||||
|
|
||||||
#: assignments/views.py:144
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is already nominated."
|
|
||||||
msgstr "Uživatel %s je již jmenován."
|
|
||||||
|
|
||||||
#: assignments/views.py:149
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was nominated successfully."
|
|
||||||
msgstr "Uchazeč %s byl úspěšně jmenován."
|
|
||||||
|
|
||||||
#: assignments/views.py:156
|
|
||||||
msgid ""
|
|
||||||
"You can not delete someone's candidature to this election because it is "
|
|
||||||
"finished."
|
|
||||||
msgstr "Nemůžete smazat něčí uchazečství o zvolení v těchto volbách, protože tyto jsou již skončeny."
|
|
||||||
|
|
||||||
#: assignments/views.py:159
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s has no status in this election."
|
|
||||||
msgstr "Uživatel %s v těchto volbách nemá žádné postavení."
|
|
||||||
|
|
||||||
#: assignments/views.py:161
|
|
||||||
#, python-format
|
|
||||||
msgid "Candidate %s was withdrawn successfully."
|
|
||||||
msgstr "Uchazeč %s byl úspěšně stažen."
|
|
||||||
|
|
||||||
#: assignments/views.py:173
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is not a candidate of this election."
|
|
||||||
msgstr "Uživatel %s není uchazečem v těchto volbách."
|
|
||||||
|
|
||||||
#: assignments/views.py:175
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully elected."
|
|
||||||
msgstr "Uživatel %s byl úspěšně zvolen."
|
|
||||||
|
|
||||||
#: assignments/views.py:179
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is not an elected candidate of this election."
|
|
||||||
msgstr "Uživatel %s není zvoleným uchazečem v těchto volbách."
|
|
||||||
|
|
||||||
#: assignments/views.py:182
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully unelected."
|
|
||||||
msgstr "Postavení uživatele/uživatelky %s jako zvoleného/zvolené byl úspěšně zrušeno."
|
|
||||||
|
|
||||||
#: assignments/views.py:192
|
|
||||||
msgid "Can not create ballot because there are no candidates."
|
|
||||||
msgstr "Nelze vyvolat hlasování, protože nejsou uchazeči."
|
|
||||||
|
|
||||||
#: assignments/views.py:195
|
|
||||||
msgid "Ballot created successfully."
|
|
||||||
msgstr "Hlasování bylo úspěšně vyvoláno."
|
|
||||||
|
|
||||||
#: assignments/views.py:210
|
|
||||||
msgid "users has to be a list of IDs."
|
|
||||||
msgstr "uživatelé musí být seznam ID."
|
|
||||||
|
|
||||||
#: assignments/views.py:237
|
|
||||||
msgid "Assignment related users successfully sorted."
|
|
||||||
msgstr "Uživatelé spojení s úkolem úspěšně roztříděni."
|
|
||||||
|
|
||||||
#: core/config.py:50 core/config.py:76
|
|
||||||
msgid "The config variable {} was not found."
|
|
||||||
msgstr "Proměnná nastavení {} nebyla nalezena."
|
|
||||||
|
|
||||||
#: core/config.py:85
|
|
||||||
#, python-format
|
|
||||||
msgid "Wrong datatype. Expected %(expected_type)s, got %(got_type)s."
|
|
||||||
msgstr "Nesprávný typ dat. Očekáváno %(expected_type)s, obdrženo %(got_type)s."
|
|
||||||
|
|
||||||
#: core/config.py:95
|
|
||||||
msgid "Invalid input. Choice does not match."
|
|
||||||
msgstr "Neplatný vstup. Výběr neodpovídá."
|
|
||||||
|
|
||||||
#: core/config.py:105
|
|
||||||
msgid "motions_comments has to be a dict."
|
|
||||||
msgstr "motions_comments musí být diktovaný text."
|
|
||||||
|
|
||||||
#: core/config.py:111
|
|
||||||
msgid "Each id has to be an int."
|
|
||||||
msgstr "Každé ID musí být vnitřní."
|
|
||||||
|
|
||||||
#: core/config.py:114
|
|
||||||
msgid "Each id has to be greater then 0."
|
|
||||||
msgstr "Každé ID musí být větší než 0"
|
|
||||||
|
|
||||||
#: core/config.py:118
|
|
||||||
msgid "Each commentsfield in motions_comments has to be a dict."
|
|
||||||
msgstr "Každý poznámkové pole v motions_comments musí být diktovaný text."
|
|
||||||
|
|
||||||
#: core/config.py:120
|
|
||||||
msgid "A name and a public property have to be given."
|
|
||||||
msgstr "Název a vlastnost public musí být zadány."
|
|
||||||
|
|
||||||
#: core/config.py:122
|
|
||||||
msgid "name has to be string."
|
|
||||||
msgstr "Název musí být řetězec."
|
|
||||||
|
|
||||||
#: core/config.py:124
|
|
||||||
msgid "public property has to be bool."
|
|
||||||
msgstr "Vlastnost public musí být booleánská hodnota."
|
|
||||||
|
|
||||||
#: core/config.py:130
|
|
||||||
msgid "This has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:137 core/config.py:153
|
|
||||||
msgid "{} has to be given."
|
|
||||||
msgstr "{} musí být zadáno."
|
|
||||||
|
|
||||||
#: core/config.py:139 core/config.py:155
|
|
||||||
msgid "{} has to be a string."
|
|
||||||
msgstr "{} musí být řetězec."
|
|
||||||
|
|
||||||
#: core/config.py:143
|
|
||||||
msgid "Translations has to be a list."
|
|
||||||
msgstr "Překlady musí být seznam."
|
|
||||||
|
|
||||||
#: core/config.py:146
|
|
||||||
msgid "Every value has to be a dict, not {}."
|
|
||||||
msgstr "Každá hodnota musí být diktovaný text ne {}."
|
|
||||||
|
|
||||||
#: core/config.py:177
|
|
||||||
msgid "Too many values for config variables {} found."
|
|
||||||
msgstr "Nalezeno příliš mnoho hodnot pro proměnnou nastavení {}."
|
|
||||||
|
|
||||||
#: core/config.py:261
|
|
||||||
msgid "Invalid value for config attribute input_type."
|
|
||||||
msgstr "Neplatná hodnota pro vlastnost nastavení input_type."
|
|
||||||
|
|
||||||
#: core/config.py:263
|
|
||||||
msgid ""
|
|
||||||
"Either config attribute 'choices' must not be None or 'input_type' must not "
|
|
||||||
"be 'choice'."
|
|
||||||
msgstr "Buď nesmí být vlastnost nastavení 'choices' žádná nebo 'input_type' nesmí být 'choice'."
|
|
||||||
|
|
||||||
#: core/config.py:266
|
|
||||||
msgid ""
|
|
||||||
"Either config attribute 'choices' must be None or 'input_type' must be "
|
|
||||||
"'choice'."
|
|
||||||
msgstr "Buď musí být vlastnost nastavení 'choices' žádná nebo 'input_type' musí být 'choice'."
|
|
||||||
|
|
||||||
#: core/config.py:276
|
|
||||||
msgid "General"
|
|
||||||
msgstr "Obecné"
|
|
||||||
|
|
||||||
#: core/views.py:277
|
|
||||||
msgid "The data has to be a list."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:280
|
|
||||||
msgid "All elements have to be dicts."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:420
|
|
||||||
msgid "The data has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:426
|
|
||||||
msgid "The id \"{}\" has to be int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:432
|
|
||||||
msgid "Prune has to be an object."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:435
|
|
||||||
msgid "The prune projector id has to be int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:440
|
|
||||||
msgid "The projector with id \"{}\" does not exist"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:444
|
|
||||||
msgid "Prune element has to be a dict or not given."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:772
|
|
||||||
msgid "All chat messages deleted successfully."
|
|
||||||
msgstr "Úspěšně smazány všechny zprávy rozhovoru."
|
|
||||||
|
|
||||||
#: mediafiles/models.py:87
|
|
||||||
msgid "unknown"
|
|
||||||
msgstr "neznámý"
|
|
||||||
|
|
||||||
#: motions/models.py:190
|
|
||||||
msgid "Motion"
|
|
||||||
msgstr "Návrh"
|
|
||||||
|
|
||||||
#: motions/models.py:744
|
|
||||||
msgid "new"
|
|
||||||
msgstr "Nový"
|
|
||||||
|
|
||||||
#: motions/models.py:969
|
|
||||||
#, python-format
|
|
||||||
msgid "%(time_and_messages)s by %(person)s"
|
|
||||||
msgstr "%(time_and_messages)s od %(person)s"
|
|
||||||
|
|
||||||
#: motions/serializers.py:36
|
|
||||||
#, python-format
|
|
||||||
msgid "Workflow %(pk)d does not exist."
|
|
||||||
msgstr "Průběh práce %(pk)d neexistuje."
|
|
||||||
|
|
||||||
#: motions/signals.py:22
|
|
||||||
msgid "submitted"
|
|
||||||
msgstr "podáno"
|
|
||||||
|
|
||||||
#: motions/signals.py:27 motions/signals.py:60
|
|
||||||
msgid "accepted"
|
|
||||||
msgstr "přijato"
|
|
||||||
|
|
||||||
#: motions/signals.py:32 motions/signals.py:66
|
|
||||||
msgid "rejected"
|
|
||||||
msgstr "odmítnuto"
|
|
||||||
|
|
||||||
#: motions/signals.py:37
|
|
||||||
msgid "not decided"
|
|
||||||
msgstr "nerozhodnuto"
|
|
||||||
|
|
||||||
#: motions/signals.py:47
|
|
||||||
msgid "published"
|
|
||||||
msgstr "zveřejněno"
|
|
||||||
|
|
||||||
#: motions/signals.py:52 motions/views.py:300
|
|
||||||
msgid "permitted"
|
|
||||||
msgstr "schváleno"
|
|
||||||
|
|
||||||
#: motions/signals.py:72
|
|
||||||
msgid "withdrawed"
|
|
||||||
msgstr "staženo"
|
|
||||||
|
|
||||||
#: motions/signals.py:77
|
|
||||||
msgid "adjourned"
|
|
||||||
msgstr "odloženo"
|
|
||||||
|
|
||||||
#: motions/signals.py:83
|
|
||||||
msgid "not concerned"
|
|
||||||
msgstr "neprobíráno"
|
|
||||||
|
|
||||||
#: motions/signals.py:89
|
|
||||||
msgid "refered to committee"
|
|
||||||
msgstr "Předáno do výboru"
|
|
||||||
|
|
||||||
#: motions/signals.py:95
|
|
||||||
msgid "needs review"
|
|
||||||
msgstr "potřeba posouzení"
|
|
||||||
|
|
||||||
#: motions/signals.py:100
|
|
||||||
msgid "rejected (not authorized)"
|
|
||||||
msgstr "odmítnuto (není schváleno)"
|
|
||||||
|
|
||||||
#: motions/views.py:110
|
|
||||||
msgid "The parent motion does not exist."
|
|
||||||
msgstr "Rodičovský návrh neexistuje."
|
|
||||||
|
|
||||||
#: motions/views.py:154
|
|
||||||
msgid "Motion created"
|
|
||||||
msgstr "Návrh vytvořen"
|
|
||||||
|
|
||||||
#: motions/views.py:256
|
|
||||||
msgid "Motion updated"
|
|
||||||
msgstr "Návrh aktualizován"
|
|
||||||
|
|
||||||
#: motions/views.py:260
|
|
||||||
msgid "All supporters removed"
|
|
||||||
msgstr "Všichni podporovatelé odstraněni"
|
|
||||||
|
|
||||||
#: motions/views.py:264
|
|
||||||
msgid "Comment {} updated"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:298 motions/views.py:310
|
|
||||||
msgid "Version"
|
|
||||||
msgstr "Verze"
|
|
||||||
|
|
||||||
#: motions/views.py:302
|
|
||||||
#, python-format
|
|
||||||
msgid "Version %d permitted successfully."
|
|
||||||
msgstr "Verze %d úspěšně schválena."
|
|
||||||
|
|
||||||
#: motions/views.py:307
|
|
||||||
msgid "You can not delete the active version of a motion."
|
|
||||||
msgstr "Nelze smazat platnou verzi návrhu."
|
|
||||||
|
|
||||||
#: motions/views.py:312
|
|
||||||
msgid "deleted"
|
|
||||||
msgstr "smazáno"
|
|
||||||
|
|
||||||
#: motions/views.py:314
|
|
||||||
#, python-format
|
|
||||||
msgid "Version %d deleted successfully."
|
|
||||||
msgstr "Verze %d úspěšně smazána."
|
|
||||||
|
|
||||||
#: motions/views.py:337
|
|
||||||
msgid "You can not support this motion."
|
|
||||||
msgstr "Nesmíte podporovat tento návrh."
|
|
||||||
|
|
||||||
#: motions/views.py:339
|
|
||||||
msgid "Motion supported"
|
|
||||||
msgstr "Návrh podporován"
|
|
||||||
|
|
||||||
#: motions/views.py:343
|
|
||||||
msgid "You have supported this motion successfully."
|
|
||||||
msgstr "Podporoval jste úspěšně tento návrh."
|
|
||||||
|
|
||||||
#: motions/views.py:348
|
|
||||||
msgid "You can not unsupport this motion."
|
|
||||||
msgstr "Nesmíte odepřít svou podporu pro tento návrh."
|
|
||||||
|
|
||||||
#: motions/views.py:350
|
|
||||||
msgid "Motion unsupported"
|
|
||||||
msgstr "Podpora pro návrh stažena"
|
|
||||||
|
|
||||||
#: motions/views.py:351
|
|
||||||
msgid "You have unsupported this motion successfully."
|
|
||||||
msgstr "Svou podporu pro návrh jste úspěšně stáhl."
|
|
||||||
|
|
||||||
#: motions/views.py:374
|
|
||||||
msgid "Invalid data. State must be an integer."
|
|
||||||
msgstr "Neplatná data. Stav musí být celé číslo."
|
|
||||||
|
|
||||||
#: motions/views.py:377
|
|
||||||
#, python-format
|
|
||||||
msgid "You can not set the state to %(state_id)d."
|
|
||||||
msgstr "Nelze nastavit stav na %(state_id)d."
|
|
||||||
|
|
||||||
#: motions/views.py:385
|
|
||||||
#, python-format
|
|
||||||
msgid "The state of the motion was set to %s."
|
|
||||||
msgstr "Stav návrhu byl nastaven na %s."
|
|
||||||
|
|
||||||
#: motions/views.py:389 motions/views.py:458 motions/views.py:726
|
|
||||||
msgid "State set to"
|
|
||||||
msgstr "Stav nastaven na"
|
|
||||||
|
|
||||||
#: motions/views.py:413
|
|
||||||
msgid "Invalid data. Recommendation must be an integer."
|
|
||||||
msgstr "Neplatná data. Doporučení musí být celé číslo."
|
|
||||||
|
|
||||||
#: motions/views.py:417
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "You can not set the recommendation to {recommendation_state_id}."
|
|
||||||
msgstr "Doporučení nelze nastavit na {recommendation_state_id}."
|
|
||||||
|
|
||||||
#: motions/views.py:427
|
|
||||||
#, python-format
|
|
||||||
msgid "The recommendation of the motion was set to %s."
|
|
||||||
msgstr "Doporučení návrhu bylo nastaveno na %s."
|
|
||||||
|
|
||||||
#: motions/views.py:431
|
|
||||||
msgid "Recommendation set to"
|
|
||||||
msgstr "Doporučení nastaveno na"
|
|
||||||
|
|
||||||
#: motions/views.py:439
|
|
||||||
msgid "Cannot set an empty recommendation."
|
|
||||||
msgstr "Nelze nastavit prázdné doporučení"
|
|
||||||
|
|
||||||
#: motions/views.py:479
|
|
||||||
msgid "Vote created"
|
|
||||||
msgstr "Hlasování vytvořeno"
|
|
||||||
|
|
||||||
#: motions/views.py:483
|
|
||||||
msgid "Vote created successfully."
|
|
||||||
msgstr "Hlasování bylo úspěšně vytvořeno."
|
|
||||||
|
|
||||||
#: motions/views.py:509
|
|
||||||
msgid "Vote updated"
|
|
||||||
msgstr "Hlasování aktualizováno"
|
|
||||||
|
|
||||||
#: motions/views.py:518
|
|
||||||
msgid "Vote deleted"
|
|
||||||
msgstr "Hlasování smazáno"
|
|
||||||
|
|
||||||
#: motions/views.py:652
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"Numbering aborted because the motion identifier \"%s\" already exists "
|
|
||||||
"outside of this category."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:675
|
|
||||||
msgid ""
|
|
||||||
"Error: At least one identifier of this category does already exist in "
|
|
||||||
"another category."
|
|
||||||
msgstr "Chyba: Alespoň jeden dentifikátor (označení dat) tohoto oboru činnosti již je v jiném oboru činnosti."
|
|
||||||
|
|
||||||
#: motions/views.py:680
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "All motions in category {category} numbered successfully."
|
|
||||||
msgstr "Všechny návrhy v oboru činnosti {category} úspěšně očíslovány."
|
|
||||||
|
|
||||||
#: motions/views.py:731
|
|
||||||
msgid "Followed recommendations successfully."
|
|
||||||
msgstr "Doporučení sledována úspěšně."
|
|
||||||
|
|
||||||
#: poll/models.py:194
|
|
||||||
msgid "majority"
|
|
||||||
msgstr "Většina"
|
|
||||||
|
|
||||||
#: poll/models.py:196 poll/models.py:198
|
|
||||||
msgid "undocumented"
|
|
||||||
msgstr "nedokumentováno"
|
|
||||||
|
|
||||||
#: poll/serializers.py:16
|
|
||||||
msgid "Value for {} must not be less than -2"
|
|
||||||
msgstr "Hodnota pro {} nesmí být menší než -2"
|
|
||||||
|
|
||||||
#: users/serializers.py:49
|
|
||||||
msgid ""
|
|
||||||
"The groups this user belongs to. A user will get all permissions granted to "
|
|
||||||
"each of his/her groups."
|
|
||||||
msgstr "Skupina, k níž tento uživatel patří. Uživatel dostane oprávnění udělená každému v jeho/její skupině."
|
|
||||||
|
|
||||||
#: users/serializers.py:72
|
|
||||||
msgid "Username, given name and surname can not all be empty."
|
|
||||||
msgstr "Uživatelské jméno, křestní jméno a příjmení nesmí být prázdné."
|
|
||||||
|
|
||||||
#: users/serializers.py:109
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "Incorrect value \"{value}\". Expected app_label.codename string."
|
|
||||||
msgstr "Nesprávná hodnota \"{value}\". Očekáván řetězec app_label.codename."
|
|
||||||
|
|
||||||
#: users/serializers.py:110
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "Invalid permission \"{value}\". Object does not exist."
|
|
||||||
msgstr "Neplatné oprávnění \"{value}\". Předmět neexistuje."
|
|
||||||
|
|
||||||
#: users/views.py:91
|
|
||||||
msgid "You can not deactivate yourself."
|
|
||||||
msgstr "Nemůžete vypnout sami sebe."
|
|
||||||
|
|
||||||
#: users/views.py:114
|
|
||||||
msgid "You can not delete yourself."
|
|
||||||
msgstr "Nemůžete smazat sami sebe."
|
|
||||||
|
|
||||||
#: users/views.py:131
|
|
||||||
msgid "Password successfully reset."
|
|
||||||
msgstr "Heslo bylo úspěšně nastaveno znovu."
|
|
||||||
|
|
||||||
#: users/views.py:172
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{number} users successfully imported."
|
|
||||||
msgstr "{number} uživatelů bylo úspěšně zavedeno."
|
|
||||||
|
|
||||||
#: users/views.py:410
|
|
||||||
msgid "Cookies have to be enabled to use OpenSlides."
|
|
||||||
msgstr "Pro používání OpenSlides musíte povolit koláčky."
|
|
||||||
|
|
||||||
#: users/views.py:413
|
|
||||||
msgid "Username or password is not correct."
|
|
||||||
msgstr "Uživatelské jméno nebo heslo není správné."
|
|
||||||
|
|
||||||
#: users/views.py:439
|
|
||||||
#, python-brace-format
|
|
||||||
msgid ""
|
|
||||||
"Installation was successfully. Use {username} and {password} for first "
|
|
||||||
"login. Important: Please change your password!"
|
|
||||||
msgstr "Instalace proběhla úspěšně. Použijte {username} a {password} při prvním přihlášení. Důležité: Změňte, prosím, své heslo!"
|
|
||||||
|
|
||||||
#: users/views.py:462
|
|
||||||
msgid "You are not authenticated."
|
|
||||||
msgstr "Nejste ověřen."
|
|
||||||
|
|
||||||
#: users/views.py:509
|
|
||||||
msgid "Old password does not match."
|
|
||||||
msgstr "Staré heslo se neshoduje."
|
|
Binary file not shown.
@ -1,673 +0,0 @@
|
|||||||
# Language file of OpenSlides used by Transifex:
|
|
||||||
# https://www.transifex.com/openslides/openslides/
|
|
||||||
# Copyright (C) 2011–2015 by OpenSlides team, see AUTHORS.
|
|
||||||
# This file is distributed under the same license as the OpenSlides package.
|
|
||||||
# Translators:
|
|
||||||
# Emanuel Schütze <emanuel.schuetze@intevation.de>, 2015-2018
|
|
||||||
# Norman Jäckel <transifex16062013@normanjaeckel.de>, 2015
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: OpenSlides\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2018-05-23 16:13+0200\n"
|
|
||||||
"PO-Revision-Date: 2018-05-23 14:31+0000\n"
|
|
||||||
"Last-Translator: Emanuel Schütze <emanuel.schuetze@intevation.de>\n"
|
|
||||||
"Language-Team: German (http://www.transifex.com/openslides/openslides/language/de/)\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Language: de\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: agenda/models.py:206
|
|
||||||
msgid "Agenda item"
|
|
||||||
msgstr "Tagesordnungspunkt"
|
|
||||||
|
|
||||||
#: agenda/models.py:207
|
|
||||||
msgid "Hidden item"
|
|
||||||
msgstr "Versteckter Eintrag"
|
|
||||||
|
|
||||||
#: agenda/models.py:356
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{user} is already on the list of speakers."
|
|
||||||
msgstr "{user} ist bereits auf der Redeliste."
|
|
||||||
|
|
||||||
#: agenda/models.py:359
|
|
||||||
msgid "An anonymous user can not be on lists of speakers."
|
|
||||||
msgstr "Anonyme Gast-Benutzer können nicht auf Redelisten stehen."
|
|
||||||
|
|
||||||
#: agenda/views.py:116
|
|
||||||
msgid "The list of speakers is closed."
|
|
||||||
msgstr "Die Redeliste ist geschlossen."
|
|
||||||
|
|
||||||
#: agenda/views.py:125 agenda/views.py:150
|
|
||||||
msgid "User does not exist."
|
|
||||||
msgstr "Benutzer existiert nicht."
|
|
||||||
|
|
||||||
#: agenda/views.py:133
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully added to the list of speakers."
|
|
||||||
msgstr "Benutzer %s wurde erfolgreich zur Redeliste hinzugefügt."
|
|
||||||
|
|
||||||
#: agenda/views.py:154
|
|
||||||
msgid "Marked has to be a bool."
|
|
||||||
msgstr "Marked muss ein Boolean sein."
|
|
||||||
|
|
||||||
#: agenda/views.py:163
|
|
||||||
msgid "The user is not in the list of speakers."
|
|
||||||
msgstr "Der Nutzer ist nicht auf der Redeliste."
|
|
||||||
|
|
||||||
#: agenda/views.py:168
|
|
||||||
msgid "You are successfully marked the speaker."
|
|
||||||
msgstr "Der Redner wurde erfolgreich markiert."
|
|
||||||
|
|
||||||
#: agenda/views.py:170
|
|
||||||
msgid "You are successfully unmarked the speaker."
|
|
||||||
msgstr "Der Redner wurde erfolgreich nicht markiert."
|
|
||||||
|
|
||||||
#: agenda/views.py:187
|
|
||||||
msgid "You are not on the list of speakers."
|
|
||||||
msgstr "Sie stehen nicht auf der Redeliste."
|
|
||||||
|
|
||||||
#: agenda/views.py:190
|
|
||||||
msgid "You are successfully removed from the list of speakers."
|
|
||||||
msgstr "Sie wurden erfolgreich von der Redeliste entfernt."
|
|
||||||
|
|
||||||
#: agenda/views.py:212
|
|
||||||
msgid "speakers have been removed from the list of speakers."
|
|
||||||
msgstr "Redner/innen wurden erfolgreich von der Redeliste entfernt."
|
|
||||||
|
|
||||||
#: agenda/views.py:214
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s has been removed from the list of speakers."
|
|
||||||
msgstr "%s wurde von der Redeliste entfernt."
|
|
||||||
|
|
||||||
#: agenda/views.py:216
|
|
||||||
msgid "No speakers have been removed from the list of speakers."
|
|
||||||
msgstr "Es wurden keine Redner/innen von der Redeliste entfernt."
|
|
||||||
|
|
||||||
#: agenda/views.py:236
|
|
||||||
msgid "The list of speakers is empty."
|
|
||||||
msgstr "Die Redeliste ist leer."
|
|
||||||
|
|
||||||
#: agenda/views.py:241
|
|
||||||
msgid "Speaker does not exist."
|
|
||||||
msgstr "Redner/in existiert nicht."
|
|
||||||
|
|
||||||
#: agenda/views.py:243
|
|
||||||
msgid "User is now speaking."
|
|
||||||
msgstr "Benutzer redet jetzt."
|
|
||||||
|
|
||||||
#: agenda/views.py:254
|
|
||||||
#, python-format
|
|
||||||
msgid "There is no one speaking at the moment according to %(item)s."
|
|
||||||
msgstr "Es spricht derzeit kein/e Redner/in zu %(item)s."
|
|
||||||
|
|
||||||
#: agenda/views.py:256
|
|
||||||
msgid "The speech is finished now."
|
|
||||||
msgstr "Die Rede ist jetzt beendet."
|
|
||||||
|
|
||||||
#: agenda/views.py:275 agenda/views.py:287 assignments/views.py:222
|
|
||||||
msgid "Invalid data."
|
|
||||||
msgstr "Ungültige Daten."
|
|
||||||
|
|
||||||
#: agenda/views.py:300
|
|
||||||
msgid "List of speakers successfully sorted."
|
|
||||||
msgstr "Die Redeliste wurde erfolgreich sortiert."
|
|
||||||
|
|
||||||
#: agenda/views.py:309
|
|
||||||
msgid "Numbering of agenda items is deactivated."
|
|
||||||
msgstr "Die Nummerierung von Tagesordnungspunkten ist deaktiviert."
|
|
||||||
|
|
||||||
#: agenda/views.py:312
|
|
||||||
msgid "The agenda has been numbered."
|
|
||||||
msgstr "Die Tagesordnung wurde nummeriert."
|
|
||||||
|
|
||||||
#: agenda/views.py:337
|
|
||||||
msgid "There must not be a hierarchical loop. Please reload the page."
|
|
||||||
msgstr "Es darf keine hierarchische Schleife vorhanden sein. Bitte laden Sie die Seite neu."
|
|
||||||
|
|
||||||
#: agenda/views.py:341
|
|
||||||
msgid "The agenda has been sorted."
|
|
||||||
msgstr "Die Tagesordnung wurde sortiert."
|
|
||||||
|
|
||||||
#: assignments/models.py:164
|
|
||||||
msgid "Election"
|
|
||||||
msgstr "Wahl"
|
|
||||||
|
|
||||||
#: assignments/serializers.py:31
|
|
||||||
msgid "Value for {} must be greater than 0"
|
|
||||||
msgstr "Wert für {} muss größer als 0 sein."
|
|
||||||
|
|
||||||
#: assignments/serializers.py:149
|
|
||||||
#, python-format
|
|
||||||
msgid "You have to submit data for %d candidates."
|
|
||||||
msgstr "Sie müssen Daten für %d Kandidaten übermitteln."
|
|
||||||
|
|
||||||
#: assignments/serializers.py:153 motions/serializers.py:236
|
|
||||||
#, python-format
|
|
||||||
msgid "You have to submit data for %d vote values."
|
|
||||||
msgstr "Sie müssen Daten für %d Stimmen übermitteln."
|
|
||||||
|
|
||||||
#: assignments/serializers.py:157 motions/serializers.py:240
|
|
||||||
#, python-format
|
|
||||||
msgid "Vote value %s is invalid."
|
|
||||||
msgstr "Wert für Stimme %s ist ungültig."
|
|
||||||
|
|
||||||
#: assignments/views.py:66
|
|
||||||
msgid "You are already elected."
|
|
||||||
msgstr "Sie sind schon gewählt."
|
|
||||||
|
|
||||||
#: assignments/views.py:76
|
|
||||||
msgid "You can not candidate to this election because it is finished."
|
|
||||||
msgstr "Sie können für diese Wahl nicht kandidieren, weil sie beendet ist."
|
|
||||||
|
|
||||||
#: assignments/views.py:85
|
|
||||||
msgid "You were nominated successfully."
|
|
||||||
msgstr "Sie wurden erfolgreich vorgeschlagen."
|
|
||||||
|
|
||||||
#: assignments/views.py:90
|
|
||||||
msgid ""
|
|
||||||
"You can not withdraw your candidature to this election because it is "
|
|
||||||
"finished."
|
|
||||||
msgstr "Sie können Ihre Kandidatur für diese Wahl nicht zurückziehen, weil sie beendet ist."
|
|
||||||
|
|
||||||
#: assignments/views.py:95
|
|
||||||
msgid "You are not a candidate of this election."
|
|
||||||
msgstr "Sie sind kein/e Kandidat/in für diese Wahl."
|
|
||||||
|
|
||||||
#: assignments/views.py:97
|
|
||||||
msgid "You have withdrawn your candidature successfully."
|
|
||||||
msgstr "Sie haben Ihre Kandidatur erfolgreich zurückgezogen."
|
|
||||||
|
|
||||||
#: assignments/views.py:106
|
|
||||||
#, python-format
|
|
||||||
msgid "Invalid data. Expected dictionary, got %s."
|
|
||||||
msgstr "Ungültige Daten. Erwartete Dictionary, erhielt %s."
|
|
||||||
|
|
||||||
#: assignments/views.py:112
|
|
||||||
msgid "Invalid data. Expected something like {\"user\": <id>}."
|
|
||||||
msgstr "Ungültige Daten. Erwartete etwas wie {\"user\": <id>}."
|
|
||||||
|
|
||||||
#: assignments/views.py:116
|
|
||||||
#, python-format
|
|
||||||
msgid "Invalid data. User %d does not exist."
|
|
||||||
msgstr "Ungültige Daten. Benutzer %d existiert nicht."
|
|
||||||
|
|
||||||
#: assignments/views.py:136
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is already elected."
|
|
||||||
msgstr "Benutzer %s ist bereits gewählt."
|
|
||||||
|
|
||||||
#: assignments/views.py:138
|
|
||||||
msgid "You can not nominate someone to this election because it is finished."
|
|
||||||
msgstr "Sie können niemanden für diese Wahl vorschlagen, weil sie beendet ist."
|
|
||||||
|
|
||||||
#: assignments/views.py:144
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is already nominated."
|
|
||||||
msgstr "Benutzer %s ist bereits vorgeschlagen."
|
|
||||||
|
|
||||||
#: assignments/views.py:149
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was nominated successfully."
|
|
||||||
msgstr "Benutzer %s wurde erfolgreich vorgeschlagen."
|
|
||||||
|
|
||||||
#: assignments/views.py:156
|
|
||||||
msgid ""
|
|
||||||
"You can not delete someone's candidature to this election because it is "
|
|
||||||
"finished."
|
|
||||||
msgstr "Sie können keine Kandidaturen für diese Wahl zurücknehmen, weil sie beendet ist."
|
|
||||||
|
|
||||||
#: assignments/views.py:159
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s has no status in this election."
|
|
||||||
msgstr "Benutzer %s hat keinen Status in dieser Wahl."
|
|
||||||
|
|
||||||
#: assignments/views.py:161
|
|
||||||
#, python-format
|
|
||||||
msgid "Candidate %s was withdrawn successfully."
|
|
||||||
msgstr "Die Kandidatur von %s wurde erfolgreich zurückgezogen."
|
|
||||||
|
|
||||||
#: assignments/views.py:173
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is not a candidate of this election."
|
|
||||||
msgstr "Benutzer %s ist kein/e Kandidat/in für diese Wahl."
|
|
||||||
|
|
||||||
#: assignments/views.py:175
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully elected."
|
|
||||||
msgstr "Benutzer %s wurde erfolgreich gewählt."
|
|
||||||
|
|
||||||
#: assignments/views.py:179
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is not an elected candidate of this election."
|
|
||||||
msgstr "Benutzer %s ist bei dieser Wahl nicht gewählt."
|
|
||||||
|
|
||||||
#: assignments/views.py:182
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully unelected."
|
|
||||||
msgstr "Der Status als Gewählte/r von Benutzer %s wurde erfolgreich aufgehoben."
|
|
||||||
|
|
||||||
#: assignments/views.py:192
|
|
||||||
msgid "Can not create ballot because there are no candidates."
|
|
||||||
msgstr "Kann keinen Wahlgang anlegen, weil es keine Kandidaten gibt."
|
|
||||||
|
|
||||||
#: assignments/views.py:195
|
|
||||||
msgid "Ballot created successfully."
|
|
||||||
msgstr "Wahlgang erfolgreich angelegt."
|
|
||||||
|
|
||||||
#: assignments/views.py:210
|
|
||||||
msgid "users has to be a list of IDs."
|
|
||||||
msgstr "Nutzer müssen eine Liste von IDs sein."
|
|
||||||
|
|
||||||
#: assignments/views.py:237
|
|
||||||
msgid "Assignment related users successfully sorted."
|
|
||||||
msgstr "Kandidaten erfolgreich sortiert."
|
|
||||||
|
|
||||||
#: core/config.py:50 core/config.py:76
|
|
||||||
msgid "The config variable {} was not found."
|
|
||||||
msgstr "Die Konfigurationsvariable {} wurde nicht gefunden."
|
|
||||||
|
|
||||||
#: core/config.py:85
|
|
||||||
#, python-format
|
|
||||||
msgid "Wrong datatype. Expected %(expected_type)s, got %(got_type)s."
|
|
||||||
msgstr "Falscher Datentyp. Erwartete %(expected_type)s, erhielt %(got_type)s."
|
|
||||||
|
|
||||||
#: core/config.py:95
|
|
||||||
msgid "Invalid input. Choice does not match."
|
|
||||||
msgstr "Ungültige Eingabe. Auswahl nicht gefunden."
|
|
||||||
|
|
||||||
#: core/config.py:105
|
|
||||||
msgid "motions_comments has to be a dict."
|
|
||||||
msgstr "motions_comments muss ein Dictionary sein."
|
|
||||||
|
|
||||||
#: core/config.py:111
|
|
||||||
msgid "Each id has to be an int."
|
|
||||||
msgstr "Jeder id muss ein int sein."
|
|
||||||
|
|
||||||
#: core/config.py:114
|
|
||||||
msgid "Each id has to be greater then 0."
|
|
||||||
msgstr "Jede id muss größer 0 sein."
|
|
||||||
|
|
||||||
#: core/config.py:118
|
|
||||||
msgid "Each commentsfield in motions_comments has to be a dict."
|
|
||||||
msgstr "Jedes commentsfield in motions_comments muss ein dict sein."
|
|
||||||
|
|
||||||
#: core/config.py:120
|
|
||||||
msgid "A name and a public property have to be given."
|
|
||||||
msgstr "Ein Name und eine public Eigenschaft müssen angegeben werden."
|
|
||||||
|
|
||||||
#: core/config.py:122
|
|
||||||
msgid "name has to be string."
|
|
||||||
msgstr "Name muss ein String sein."
|
|
||||||
|
|
||||||
#: core/config.py:124
|
|
||||||
msgid "public property has to be bool."
|
|
||||||
msgstr "Public-Eigenschaft muss ein Boolean sein."
|
|
||||||
|
|
||||||
#: core/config.py:130
|
|
||||||
msgid "This has to be a dict."
|
|
||||||
msgstr "Dies muss ein Dictionary sein."
|
|
||||||
|
|
||||||
#: core/config.py:137 core/config.py:153
|
|
||||||
msgid "{} has to be given."
|
|
||||||
msgstr "{} muss angegeben werden."
|
|
||||||
|
|
||||||
#: core/config.py:139 core/config.py:155
|
|
||||||
msgid "{} has to be a string."
|
|
||||||
msgstr "{} muss ein String sein."
|
|
||||||
|
|
||||||
#: core/config.py:143
|
|
||||||
msgid "Translations has to be a list."
|
|
||||||
msgstr "Translations muss ein dict sein."
|
|
||||||
|
|
||||||
#: core/config.py:146
|
|
||||||
msgid "Every value has to be a dict, not {}."
|
|
||||||
msgstr "Jeder Wert muss ein dict sein, nicht {}."
|
|
||||||
|
|
||||||
#: core/config.py:177
|
|
||||||
msgid "Too many values for config variables {} found."
|
|
||||||
msgstr "Zu viele Werte für Konfigurationsvariablen {} gefunden."
|
|
||||||
|
|
||||||
#: core/config.py:261
|
|
||||||
msgid "Invalid value for config attribute input_type."
|
|
||||||
msgstr "Ungültiger Wert für Konfigurationsattribut input_type."
|
|
||||||
|
|
||||||
#: core/config.py:263
|
|
||||||
msgid ""
|
|
||||||
"Either config attribute 'choices' must not be None or 'input_type' must not "
|
|
||||||
"be 'choice'."
|
|
||||||
msgstr "Entweder das Konfigurationsattribut 'choices' darf nicht None sein oder 'input_type' darf nicht 'choice' sein."
|
|
||||||
|
|
||||||
#: core/config.py:266
|
|
||||||
msgid ""
|
|
||||||
"Either config attribute 'choices' must be None or 'input_type' must be "
|
|
||||||
"'choice'."
|
|
||||||
msgstr "Entweder das Konfigurationsattribut 'choices' muss None sein oder 'input_type' muss 'choice' sein."
|
|
||||||
|
|
||||||
#: core/config.py:276
|
|
||||||
msgid "General"
|
|
||||||
msgstr "Allgemein"
|
|
||||||
|
|
||||||
#: core/views.py:277
|
|
||||||
msgid "The data has to be a list."
|
|
||||||
msgstr "Die Daten müssen eine Liste sein."
|
|
||||||
|
|
||||||
#: core/views.py:280
|
|
||||||
msgid "All elements have to be dicts."
|
|
||||||
msgstr "Alle Elemente müssen ein Dictionary sein."
|
|
||||||
|
|
||||||
#: core/views.py:420
|
|
||||||
msgid "The data has to be a dict."
|
|
||||||
msgstr "Die Daten müssen ein Dictionary sein."
|
|
||||||
|
|
||||||
#: core/views.py:426
|
|
||||||
msgid "The id \"{}\" has to be int."
|
|
||||||
msgstr "Die id \"{}\" muss ein Integer sein."
|
|
||||||
|
|
||||||
#: core/views.py:432
|
|
||||||
msgid "Prune has to be an object."
|
|
||||||
msgstr "Prune muss ein Object sein."
|
|
||||||
|
|
||||||
#: core/views.py:435
|
|
||||||
msgid "The prune projector id has to be int."
|
|
||||||
msgstr "Die prune projector id muss ein Integer sein."
|
|
||||||
|
|
||||||
#: core/views.py:440
|
|
||||||
msgid "The projector with id \"{}\" does not exist"
|
|
||||||
msgstr "Der Projektor mit id \"{}\" existiert nicht."
|
|
||||||
|
|
||||||
#: core/views.py:444
|
|
||||||
msgid "Prune element has to be a dict or not given."
|
|
||||||
msgstr "Prune element muss ein Dictionary oder nicht angegeben sein."
|
|
||||||
|
|
||||||
#: core/views.py:772
|
|
||||||
msgid "All chat messages deleted successfully."
|
|
||||||
msgstr "Alle Chatnachrichten erfolgreich gelöscht."
|
|
||||||
|
|
||||||
#: mediafiles/models.py:87
|
|
||||||
msgid "unknown"
|
|
||||||
msgstr "unbekannt"
|
|
||||||
|
|
||||||
#: motions/models.py:190
|
|
||||||
msgid "Motion"
|
|
||||||
msgstr "Antrag"
|
|
||||||
|
|
||||||
#: motions/models.py:744
|
|
||||||
msgid "new"
|
|
||||||
msgstr "Neu"
|
|
||||||
|
|
||||||
#: motions/models.py:969
|
|
||||||
#, python-format
|
|
||||||
msgid "%(time_and_messages)s by %(person)s"
|
|
||||||
msgstr "%(time_and_messages)s durch %(person)s"
|
|
||||||
|
|
||||||
#: motions/serializers.py:36
|
|
||||||
#, python-format
|
|
||||||
msgid "Workflow %(pk)d does not exist."
|
|
||||||
msgstr "Arbeitsablauf %(pk)d existiert nicht."
|
|
||||||
|
|
||||||
#: motions/signals.py:22
|
|
||||||
msgid "submitted"
|
|
||||||
msgstr "eingereicht"
|
|
||||||
|
|
||||||
#: motions/signals.py:27 motions/signals.py:60
|
|
||||||
msgid "accepted"
|
|
||||||
msgstr "angenommen"
|
|
||||||
|
|
||||||
#: motions/signals.py:32 motions/signals.py:66
|
|
||||||
msgid "rejected"
|
|
||||||
msgstr "abgelehnt"
|
|
||||||
|
|
||||||
#: motions/signals.py:37
|
|
||||||
msgid "not decided"
|
|
||||||
msgstr "nicht entschieden"
|
|
||||||
|
|
||||||
#: motions/signals.py:47
|
|
||||||
msgid "published"
|
|
||||||
msgstr "veröffentlicht"
|
|
||||||
|
|
||||||
#: motions/signals.py:52 motions/views.py:300
|
|
||||||
msgid "permitted"
|
|
||||||
msgstr "zugelassen"
|
|
||||||
|
|
||||||
#: motions/signals.py:72
|
|
||||||
msgid "withdrawed"
|
|
||||||
msgstr "zurückgezogen"
|
|
||||||
|
|
||||||
#: motions/signals.py:77
|
|
||||||
msgid "adjourned"
|
|
||||||
msgstr "vertagt"
|
|
||||||
|
|
||||||
#: motions/signals.py:83
|
|
||||||
msgid "not concerned"
|
|
||||||
msgstr "nicht befasst"
|
|
||||||
|
|
||||||
#: motions/signals.py:89
|
|
||||||
msgid "refered to committee"
|
|
||||||
msgstr "in Ausschuss verwiesen"
|
|
||||||
|
|
||||||
#: motions/signals.py:95
|
|
||||||
msgid "needs review"
|
|
||||||
msgstr "Benötigt Review"
|
|
||||||
|
|
||||||
#: motions/signals.py:100
|
|
||||||
msgid "rejected (not authorized)"
|
|
||||||
msgstr "Verworfen (nicht zulässig)"
|
|
||||||
|
|
||||||
#: motions/views.py:110
|
|
||||||
msgid "The parent motion does not exist."
|
|
||||||
msgstr "Der Eltern-Antrag existiert nicht."
|
|
||||||
|
|
||||||
#: motions/views.py:154
|
|
||||||
msgid "Motion created"
|
|
||||||
msgstr "Antrag erstellt"
|
|
||||||
|
|
||||||
#: motions/views.py:256
|
|
||||||
msgid "Motion updated"
|
|
||||||
msgstr "Antrag aktualisiert"
|
|
||||||
|
|
||||||
#: motions/views.py:260
|
|
||||||
msgid "All supporters removed"
|
|
||||||
msgstr "Alle Unterstützer entfernt"
|
|
||||||
|
|
||||||
#: motions/views.py:264
|
|
||||||
msgid "Comment {} updated"
|
|
||||||
msgstr "Kommentar {} aktualisiert"
|
|
||||||
|
|
||||||
#: motions/views.py:298 motions/views.py:310
|
|
||||||
msgid "Version"
|
|
||||||
msgstr "Version"
|
|
||||||
|
|
||||||
#: motions/views.py:302
|
|
||||||
#, python-format
|
|
||||||
msgid "Version %d permitted successfully."
|
|
||||||
msgstr "Version %d erfolgreich zugelassen"
|
|
||||||
|
|
||||||
#: motions/views.py:307
|
|
||||||
msgid "You can not delete the active version of a motion."
|
|
||||||
msgstr "Sie dürfen die aktive Version eines Antrags nicht löschen."
|
|
||||||
|
|
||||||
#: motions/views.py:312
|
|
||||||
msgid "deleted"
|
|
||||||
msgstr "Gelöscht"
|
|
||||||
|
|
||||||
#: motions/views.py:314
|
|
||||||
#, python-format
|
|
||||||
msgid "Version %d deleted successfully."
|
|
||||||
msgstr "Version %d erfolgreich gelöscht."
|
|
||||||
|
|
||||||
#: motions/views.py:337
|
|
||||||
msgid "You can not support this motion."
|
|
||||||
msgstr "Sie dürfen diesen Antrag nicht unterstützen."
|
|
||||||
|
|
||||||
#: motions/views.py:339
|
|
||||||
msgid "Motion supported"
|
|
||||||
msgstr "Antrag unterstützt"
|
|
||||||
|
|
||||||
#: motions/views.py:343
|
|
||||||
msgid "You have supported this motion successfully."
|
|
||||||
msgstr "Sie haben den Antrag erfolgreich unterstützt."
|
|
||||||
|
|
||||||
#: motions/views.py:348
|
|
||||||
msgid "You can not unsupport this motion."
|
|
||||||
msgstr "Sie dürfen diesem Antrag Ihre Unterstützung nicht entziehen."
|
|
||||||
|
|
||||||
#: motions/views.py:350
|
|
||||||
msgid "Motion unsupported"
|
|
||||||
msgstr "Unterstützung zurückgezogen"
|
|
||||||
|
|
||||||
#: motions/views.py:351
|
|
||||||
msgid "You have unsupported this motion successfully."
|
|
||||||
msgstr "Sie haben dem Antrag erfolgreich Ihre Unterstützung entzogen."
|
|
||||||
|
|
||||||
#: motions/views.py:374
|
|
||||||
msgid "Invalid data. State must be an integer."
|
|
||||||
msgstr "Ungültige Daten. Status muss eine Ganzzahl sein."
|
|
||||||
|
|
||||||
#: motions/views.py:377
|
|
||||||
#, python-format
|
|
||||||
msgid "You can not set the state to %(state_id)d."
|
|
||||||
msgstr "Sie dürfen den Antragsstatus nicht auf %(state_id)d setzen."
|
|
||||||
|
|
||||||
#: motions/views.py:385
|
|
||||||
#, python-format
|
|
||||||
msgid "The state of the motion was set to %s."
|
|
||||||
msgstr "Der Status des Antrags wurde auf %s gesetzt."
|
|
||||||
|
|
||||||
#: motions/views.py:389 motions/views.py:458 motions/views.py:726
|
|
||||||
msgid "State set to"
|
|
||||||
msgstr "Status gesetzt auf"
|
|
||||||
|
|
||||||
#: motions/views.py:413
|
|
||||||
msgid "Invalid data. Recommendation must be an integer."
|
|
||||||
msgstr "Ungültige Daten. Empfehlung muss ein Integer sein."
|
|
||||||
|
|
||||||
#: motions/views.py:417
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "You can not set the recommendation to {recommendation_state_id}."
|
|
||||||
msgstr "Sie können die Empfehlung nicht auf {recommendation_state_id} setzen."
|
|
||||||
|
|
||||||
#: motions/views.py:427
|
|
||||||
#, python-format
|
|
||||||
msgid "The recommendation of the motion was set to %s."
|
|
||||||
msgstr "Die Empfehlung des Antrags wurde auf %s gesetzt."
|
|
||||||
|
|
||||||
#: motions/views.py:431
|
|
||||||
msgid "Recommendation set to"
|
|
||||||
msgstr "Empfehlung gesetzt auf"
|
|
||||||
|
|
||||||
#: motions/views.py:439
|
|
||||||
msgid "Cannot set an empty recommendation."
|
|
||||||
msgstr "Eine leere Empfehlung kann nicht gesetzt werden."
|
|
||||||
|
|
||||||
#: motions/views.py:479
|
|
||||||
msgid "Vote created"
|
|
||||||
msgstr "Abstimmung erstellt"
|
|
||||||
|
|
||||||
#: motions/views.py:483
|
|
||||||
msgid "Vote created successfully."
|
|
||||||
msgstr "Abstimmung erfolgreich angelegt."
|
|
||||||
|
|
||||||
#: motions/views.py:509
|
|
||||||
msgid "Vote updated"
|
|
||||||
msgstr "Abstimmung aktualisiert"
|
|
||||||
|
|
||||||
#: motions/views.py:518
|
|
||||||
msgid "Vote deleted"
|
|
||||||
msgstr "Abstimmung gelöscht"
|
|
||||||
|
|
||||||
#: motions/views.py:652
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"Numbering aborted because the motion identifier \"%s\" already exists "
|
|
||||||
"outside of this category."
|
|
||||||
msgstr "Die Nummerierung wurde abgebrochen, weil der Antragsbezeichner \"%s\" bereits außerhalb dieses Sachgebiets existiert."
|
|
||||||
|
|
||||||
#: motions/views.py:675
|
|
||||||
msgid ""
|
|
||||||
"Error: At least one identifier of this category does already exist in "
|
|
||||||
"another category."
|
|
||||||
msgstr "Fehler: Mindestens ein Bezeichner von diesem Sachgebiet existiert bereits in einem anderen Sachgebiet."
|
|
||||||
|
|
||||||
#: motions/views.py:680
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "All motions in category {category} numbered successfully."
|
|
||||||
msgstr "Alle Anträge im Sachgebiet {category} wurden erfolgreich nummeriert."
|
|
||||||
|
|
||||||
#: motions/views.py:731
|
|
||||||
msgid "Followed recommendations successfully."
|
|
||||||
msgstr "Empfehlungen erfolgreich gefolgt."
|
|
||||||
|
|
||||||
#: poll/models.py:194
|
|
||||||
msgid "majority"
|
|
||||||
msgstr "Mehrheit"
|
|
||||||
|
|
||||||
#: poll/models.py:196 poll/models.py:198
|
|
||||||
msgid "undocumented"
|
|
||||||
msgstr "nicht erfasst"
|
|
||||||
|
|
||||||
#: poll/serializers.py:16
|
|
||||||
msgid "Value for {} must not be less than -2"
|
|
||||||
msgstr "Wert für {} darf nicht kleiner -2 sein."
|
|
||||||
|
|
||||||
#: users/serializers.py:49
|
|
||||||
msgid ""
|
|
||||||
"The groups this user belongs to. A user will get all permissions granted to "
|
|
||||||
"each of his/her groups."
|
|
||||||
msgstr "Die Gruppen zu denen dieser Benutzer gehört. Ein Benutzer erhält alle Berechtigungen, die diesen Gruppen zugeordnet sind."
|
|
||||||
|
|
||||||
#: users/serializers.py:72
|
|
||||||
msgid "Username, given name and surname can not all be empty."
|
|
||||||
msgstr "Benutzername, Vorname und Nachname dürfen nicht alle leer sein."
|
|
||||||
|
|
||||||
#: users/serializers.py:109
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "Incorrect value \"{value}\". Expected app_label.codename string."
|
|
||||||
msgstr "Ungültiger Wert \"{value}\". Erwartete Zeichenkette app_label.codename."
|
|
||||||
|
|
||||||
#: users/serializers.py:110
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "Invalid permission \"{value}\". Object does not exist."
|
|
||||||
msgstr "Ungültige Berechtigung \"{value}\". Objekt existiert nicht."
|
|
||||||
|
|
||||||
#: users/views.py:91
|
|
||||||
msgid "You can not deactivate yourself."
|
|
||||||
msgstr "Sie dürfen sich nicht selbst deaktivieren."
|
|
||||||
|
|
||||||
#: users/views.py:114
|
|
||||||
msgid "You can not delete yourself."
|
|
||||||
msgstr "Sie dürfen sich nicht selbst löschen."
|
|
||||||
|
|
||||||
#: users/views.py:131
|
|
||||||
msgid "Password successfully reset."
|
|
||||||
msgstr "Passwort wurde erfolgreich zurückgesetzt."
|
|
||||||
|
|
||||||
#: users/views.py:172
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{number} users successfully imported."
|
|
||||||
msgstr "{number} Teilnehmer/innen wurden erfolgreich importiert."
|
|
||||||
|
|
||||||
#: users/views.py:410
|
|
||||||
msgid "Cookies have to be enabled to use OpenSlides."
|
|
||||||
msgstr "Cookies müssen aktiviert sein, um OpenSlides verwenden zu können."
|
|
||||||
|
|
||||||
#: users/views.py:413
|
|
||||||
msgid "Username or password is not correct."
|
|
||||||
msgstr "Benutzername oder Passwort war nicht korrekt."
|
|
||||||
|
|
||||||
#: users/views.py:439
|
|
||||||
#, python-brace-format
|
|
||||||
msgid ""
|
|
||||||
"Installation was successfully. Use {username} and {password} for first "
|
|
||||||
"login. Important: Please change your password!"
|
|
||||||
msgstr "Die Installation war erfolgreich. Verwenden Sie {username} und {password} für den ersten Login. Wichtig: Bitte ändern Sie Ihr Passwort!"
|
|
||||||
|
|
||||||
#: users/views.py:462
|
|
||||||
msgid "You are not authenticated."
|
|
||||||
msgstr "Sie sind nicht authentifiziert."
|
|
||||||
|
|
||||||
#: users/views.py:509
|
|
||||||
msgid "Old password does not match."
|
|
||||||
msgstr "Das alte Passwort stimmt nicht überein."
|
|
@ -1,665 +0,0 @@
|
|||||||
# Language file of OpenSlides used by Transifex:
|
|
||||||
# https://www.transifex.com/openslides/openslides/
|
|
||||||
# Copyright (C) 2011–2015 by OpenSlides team, see AUTHORS.
|
|
||||||
# This file is distributed under the same license as the OpenSlides package.
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2018-05-23 16:13+0200\n"
|
|
||||||
"Language: en\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
|
|
||||||
#: agenda/models.py:206
|
|
||||||
msgid "Agenda item"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/models.py:207
|
|
||||||
msgid "Hidden item"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/models.py:356
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{user} is already on the list of speakers."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/models.py:359
|
|
||||||
msgid "An anonymous user can not be on lists of speakers."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:116
|
|
||||||
msgid "The list of speakers is closed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:125 agenda/views.py:150
|
|
||||||
msgid "User does not exist."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:133
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully added to the list of speakers."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:154
|
|
||||||
msgid "Marked has to be a bool."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:163
|
|
||||||
msgid "The user is not in the list of speakers."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:168
|
|
||||||
msgid "You are successfully marked the speaker."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:170
|
|
||||||
msgid "You are successfully unmarked the speaker."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:187
|
|
||||||
msgid "You are not on the list of speakers."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:190
|
|
||||||
msgid "You are successfully removed from the list of speakers."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:212
|
|
||||||
msgid "speakers have been removed from the list of speakers."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:214
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s has been removed from the list of speakers."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:216
|
|
||||||
msgid "No speakers have been removed from the list of speakers."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:236
|
|
||||||
msgid "The list of speakers is empty."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:241
|
|
||||||
msgid "Speaker does not exist."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:243
|
|
||||||
msgid "User is now speaking."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:254
|
|
||||||
#, python-format
|
|
||||||
msgid "There is no one speaking at the moment according to %(item)s."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:256
|
|
||||||
msgid "The speech is finished now."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:275 agenda/views.py:287 assignments/views.py:222
|
|
||||||
msgid "Invalid data."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:300
|
|
||||||
msgid "List of speakers successfully sorted."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:309
|
|
||||||
msgid "Numbering of agenda items is deactivated."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:312
|
|
||||||
msgid "The agenda has been numbered."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:337
|
|
||||||
msgid "There must not be a hierarchical loop. Please reload the page."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:341
|
|
||||||
msgid "The agenda has been sorted."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/models.py:164
|
|
||||||
msgid "Election"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/serializers.py:31
|
|
||||||
msgid "Value for {} must be greater than 0"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/serializers.py:149
|
|
||||||
#, python-format
|
|
||||||
msgid "You have to submit data for %d candidates."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/serializers.py:153 motions/serializers.py:236
|
|
||||||
#, python-format
|
|
||||||
msgid "You have to submit data for %d vote values."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/serializers.py:157 motions/serializers.py:240
|
|
||||||
#, python-format
|
|
||||||
msgid "Vote value %s is invalid."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:66
|
|
||||||
msgid "You are already elected."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:76
|
|
||||||
msgid "You can not candidate to this election because it is finished."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:85
|
|
||||||
msgid "You were nominated successfully."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:90
|
|
||||||
msgid ""
|
|
||||||
"You can not withdraw your candidature to this election because it is "
|
|
||||||
"finished."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:95
|
|
||||||
msgid "You are not a candidate of this election."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:97
|
|
||||||
msgid "You have withdrawn your candidature successfully."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:106
|
|
||||||
#, python-format
|
|
||||||
msgid "Invalid data. Expected dictionary, got %s."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:112
|
|
||||||
msgid "Invalid data. Expected something like {\"user\": <id>}."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:116
|
|
||||||
#, python-format
|
|
||||||
msgid "Invalid data. User %d does not exist."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:136
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is already elected."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:138
|
|
||||||
msgid "You can not nominate someone to this election because it is finished."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:144
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is already nominated."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:149
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was nominated successfully."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:156
|
|
||||||
msgid ""
|
|
||||||
"You can not delete someone's candidature to this election because it is "
|
|
||||||
"finished."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:159
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s has no status in this election."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:161
|
|
||||||
#, python-format
|
|
||||||
msgid "Candidate %s was withdrawn successfully."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:173
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is not a candidate of this election."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:175
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully elected."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:179
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is not an elected candidate of this election."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:182
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully unelected."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:192
|
|
||||||
msgid "Can not create ballot because there are no candidates."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:195
|
|
||||||
msgid "Ballot created successfully."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:210
|
|
||||||
msgid "users has to be a list of IDs."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assignments/views.py:237
|
|
||||||
msgid "Assignment related users successfully sorted."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:50 core/config.py:76
|
|
||||||
msgid "The config variable {} was not found."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:85
|
|
||||||
#, python-format
|
|
||||||
msgid "Wrong datatype. Expected %(expected_type)s, got %(got_type)s."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:95
|
|
||||||
msgid "Invalid input. Choice does not match."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:105
|
|
||||||
msgid "motions_comments has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:111
|
|
||||||
msgid "Each id has to be an int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:114
|
|
||||||
msgid "Each id has to be greater then 0."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:118
|
|
||||||
msgid "Each commentsfield in motions_comments has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:120
|
|
||||||
msgid "A name and a public property have to be given."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:122
|
|
||||||
msgid "name has to be string."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:124
|
|
||||||
msgid "public property has to be bool."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:130
|
|
||||||
msgid "This has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:137 core/config.py:153
|
|
||||||
msgid "{} has to be given."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:139 core/config.py:155
|
|
||||||
msgid "{} has to be a string."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:143
|
|
||||||
msgid "Translations has to be a list."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:146
|
|
||||||
msgid "Every value has to be a dict, not {}."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:177
|
|
||||||
msgid "Too many values for config variables {} found."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:261
|
|
||||||
msgid "Invalid value for config attribute input_type."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:263
|
|
||||||
msgid ""
|
|
||||||
"Either config attribute 'choices' must not be None or 'input_type' must not "
|
|
||||||
"be 'choice'."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:266
|
|
||||||
msgid ""
|
|
||||||
"Either config attribute 'choices' must be None or 'input_type' must be "
|
|
||||||
"'choice'."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:276
|
|
||||||
msgid "General"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:277
|
|
||||||
msgid "The data has to be a list."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:280
|
|
||||||
msgid "All elements have to be dicts."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:420
|
|
||||||
msgid "The data has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:426
|
|
||||||
msgid "The id \"{}\" has to be int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:432
|
|
||||||
msgid "Prune has to be an object."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:435
|
|
||||||
msgid "The prune projector id has to be int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:440
|
|
||||||
msgid "The projector with id \"{}\" does not exist"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:444
|
|
||||||
msgid "Prune element has to be a dict or not given."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:772
|
|
||||||
msgid "All chat messages deleted successfully."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: mediafiles/models.py:87
|
|
||||||
msgid "unknown"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/models.py:190
|
|
||||||
msgid "Motion"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/models.py:744
|
|
||||||
msgid "new"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/models.py:969
|
|
||||||
#, python-format
|
|
||||||
msgid "%(time_and_messages)s by %(person)s"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/serializers.py:36
|
|
||||||
#, python-format
|
|
||||||
msgid "Workflow %(pk)d does not exist."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/signals.py:22
|
|
||||||
msgid "submitted"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/signals.py:27 motions/signals.py:60
|
|
||||||
msgid "accepted"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/signals.py:32 motions/signals.py:66
|
|
||||||
msgid "rejected"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/signals.py:37
|
|
||||||
msgid "not decided"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/signals.py:47
|
|
||||||
msgid "published"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/signals.py:52 motions/views.py:300
|
|
||||||
msgid "permitted"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/signals.py:72
|
|
||||||
msgid "withdrawed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/signals.py:77
|
|
||||||
msgid "adjourned"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/signals.py:83
|
|
||||||
msgid "not concerned"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/signals.py:89
|
|
||||||
msgid "refered to committee"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/signals.py:95
|
|
||||||
msgid "needs review"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/signals.py:100
|
|
||||||
msgid "rejected (not authorized)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:110
|
|
||||||
msgid "The parent motion does not exist."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:154
|
|
||||||
msgid "Motion created"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:256
|
|
||||||
msgid "Motion updated"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:260
|
|
||||||
msgid "All supporters removed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:264
|
|
||||||
msgid "Comment {} updated"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:298 motions/views.py:310
|
|
||||||
msgid "Version"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:302
|
|
||||||
#, python-format
|
|
||||||
msgid "Version %d permitted successfully."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:307
|
|
||||||
msgid "You can not delete the active version of a motion."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:312
|
|
||||||
msgid "deleted"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:314
|
|
||||||
#, python-format
|
|
||||||
msgid "Version %d deleted successfully."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:337
|
|
||||||
msgid "You can not support this motion."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:339
|
|
||||||
msgid "Motion supported"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:343
|
|
||||||
msgid "You have supported this motion successfully."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:348
|
|
||||||
msgid "You can not unsupport this motion."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:350
|
|
||||||
msgid "Motion unsupported"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:351
|
|
||||||
msgid "You have unsupported this motion successfully."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:374
|
|
||||||
msgid "Invalid data. State must be an integer."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:377
|
|
||||||
#, python-format
|
|
||||||
msgid "You can not set the state to %(state_id)d."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:385
|
|
||||||
#, python-format
|
|
||||||
msgid "The state of the motion was set to %s."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:389 motions/views.py:458 motions/views.py:726
|
|
||||||
msgid "State set to"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:413
|
|
||||||
msgid "Invalid data. Recommendation must be an integer."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:417
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "You can not set the recommendation to {recommendation_state_id}."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:427
|
|
||||||
#, python-format
|
|
||||||
msgid "The recommendation of the motion was set to %s."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:431
|
|
||||||
msgid "Recommendation set to"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:439
|
|
||||||
msgid "Cannot set an empty recommendation."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:479
|
|
||||||
msgid "Vote created"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:483
|
|
||||||
msgid "Vote created successfully."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:509
|
|
||||||
msgid "Vote updated"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:518
|
|
||||||
msgid "Vote deleted"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:652
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"Numbering aborted because the motion identifier \"%s\" already exists "
|
|
||||||
"outside of this category."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:675
|
|
||||||
msgid ""
|
|
||||||
"Error: At least one identifier of this category does already exist in "
|
|
||||||
"another category."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:680
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "All motions in category {category} numbered successfully."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:731
|
|
||||||
msgid "Followed recommendations successfully."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: poll/models.py:194
|
|
||||||
msgid "majority"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: poll/models.py:196 poll/models.py:198
|
|
||||||
msgid "undocumented"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: poll/serializers.py:16
|
|
||||||
msgid "Value for {} must not be less than -2"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/serializers.py:49
|
|
||||||
msgid ""
|
|
||||||
"The groups this user belongs to. A user will get all permissions granted to "
|
|
||||||
"each of his/her groups."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/serializers.py:72
|
|
||||||
msgid "Username, given name and surname can not all be empty."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/serializers.py:109
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "Incorrect value \"{value}\". Expected app_label.codename string."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/serializers.py:110
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "Invalid permission \"{value}\". Object does not exist."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/views.py:91
|
|
||||||
msgid "You can not deactivate yourself."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/views.py:114
|
|
||||||
msgid "You can not delete yourself."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/views.py:131
|
|
||||||
msgid "Password successfully reset."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/views.py:172
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{number} users successfully imported."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/views.py:410
|
|
||||||
msgid "Cookies have to be enabled to use OpenSlides."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/views.py:413
|
|
||||||
msgid "Username or password is not correct."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/views.py:439
|
|
||||||
#, python-brace-format
|
|
||||||
msgid ""
|
|
||||||
"Installation was successfully. Use {username} and {password} for first "
|
|
||||||
"login. Important: Please change your password!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/views.py:462
|
|
||||||
msgid "You are not authenticated."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/views.py:509
|
|
||||||
msgid "Old password does not match."
|
|
||||||
msgstr ""
|
|
Binary file not shown.
@ -1,673 +0,0 @@
|
|||||||
# Language file of OpenSlides used by Transifex:
|
|
||||||
# https://www.transifex.com/openslides/openslides/
|
|
||||||
# Copyright (C) 2011–2015 by OpenSlides team, see AUTHORS.
|
|
||||||
# This file is distributed under the same license as the OpenSlides package.
|
|
||||||
# Translators:
|
|
||||||
# johnfelipe <ingenierofelipeurrego@gmail.com>, 2016
|
|
||||||
# Maximilian Krambach <maximilian.krambach@gmx.de>, 2016-2017
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: OpenSlides\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2018-05-23 16:13+0200\n"
|
|
||||||
"PO-Revision-Date: 2018-05-23 14:15+0000\n"
|
|
||||||
"Last-Translator: Emanuel Schütze <emanuel.schuetze@intevation.de>\n"
|
|
||||||
"Language-Team: Spanish (http://www.transifex.com/openslides/openslides/language/es/)\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Language: es\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: agenda/models.py:206
|
|
||||||
msgid "Agenda item"
|
|
||||||
msgstr "Item de la Agenda"
|
|
||||||
|
|
||||||
#: agenda/models.py:207
|
|
||||||
msgid "Hidden item"
|
|
||||||
msgstr "Elemento oculto"
|
|
||||||
|
|
||||||
#: agenda/models.py:356
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{user} is already on the list of speakers."
|
|
||||||
msgstr "{user} ya está en la lista de oradores."
|
|
||||||
|
|
||||||
#: agenda/models.py:359
|
|
||||||
msgid "An anonymous user can not be on lists of speakers."
|
|
||||||
msgstr "Un usuario anónimo no puede estar en listas de oradores."
|
|
||||||
|
|
||||||
#: agenda/views.py:116
|
|
||||||
msgid "The list of speakers is closed."
|
|
||||||
msgstr "La lista de oradores se cerró."
|
|
||||||
|
|
||||||
#: agenda/views.py:125 agenda/views.py:150
|
|
||||||
msgid "User does not exist."
|
|
||||||
msgstr "El usuario no existe."
|
|
||||||
|
|
||||||
#: agenda/views.py:133
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully added to the list of speakers."
|
|
||||||
msgstr "Usuario %s se ha añadido correctamente a la lista de oradores."
|
|
||||||
|
|
||||||
#: agenda/views.py:154
|
|
||||||
msgid "Marked has to be a bool."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:163
|
|
||||||
msgid "The user is not in the list of speakers."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:168
|
|
||||||
msgid "You are successfully marked the speaker."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:170
|
|
||||||
msgid "You are successfully unmarked the speaker."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:187
|
|
||||||
msgid "You are not on the list of speakers."
|
|
||||||
msgstr "Usted no está en la lista de oradores."
|
|
||||||
|
|
||||||
#: agenda/views.py:190
|
|
||||||
msgid "You are successfully removed from the list of speakers."
|
|
||||||
msgstr "Usted ha sido eliminado de la lista de oradores."
|
|
||||||
|
|
||||||
#: agenda/views.py:212
|
|
||||||
msgid "speakers have been removed from the list of speakers."
|
|
||||||
msgstr "oradores han sido eliminados de la lista de oradores."
|
|
||||||
|
|
||||||
#: agenda/views.py:214
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s has been removed from the list of speakers."
|
|
||||||
msgstr "Orador %s ha sido eliminado de la lista de oradores."
|
|
||||||
|
|
||||||
#: agenda/views.py:216
|
|
||||||
msgid "No speakers have been removed from the list of speakers."
|
|
||||||
msgstr "Ningun orador ha sido eliminado de la lista de oradores."
|
|
||||||
|
|
||||||
#: agenda/views.py:236
|
|
||||||
msgid "The list of speakers is empty."
|
|
||||||
msgstr "La lista de oradores está vacía."
|
|
||||||
|
|
||||||
#: agenda/views.py:241
|
|
||||||
msgid "Speaker does not exist."
|
|
||||||
msgstr "El orador no existe."
|
|
||||||
|
|
||||||
#: agenda/views.py:243
|
|
||||||
msgid "User is now speaking."
|
|
||||||
msgstr "El usuario está hablando."
|
|
||||||
|
|
||||||
#: agenda/views.py:254
|
|
||||||
#, python-format
|
|
||||||
msgid "There is no one speaking at the moment according to %(item)s."
|
|
||||||
msgstr "No hay nadie hablando acerca de %(item)s."
|
|
||||||
|
|
||||||
#: agenda/views.py:256
|
|
||||||
msgid "The speech is finished now."
|
|
||||||
msgstr "El discurso está terminado ahora."
|
|
||||||
|
|
||||||
#: agenda/views.py:275 agenda/views.py:287 assignments/views.py:222
|
|
||||||
msgid "Invalid data."
|
|
||||||
msgstr "Datos inválidos."
|
|
||||||
|
|
||||||
#: agenda/views.py:300
|
|
||||||
msgid "List of speakers successfully sorted."
|
|
||||||
msgstr "Lista de oradores ha sido ordenada correctamente."
|
|
||||||
|
|
||||||
#: agenda/views.py:309
|
|
||||||
msgid "Numbering of agenda items is deactivated."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:312
|
|
||||||
msgid "The agenda has been numbered."
|
|
||||||
msgstr "Los temas del programa han sido numerados."
|
|
||||||
|
|
||||||
#: agenda/views.py:337
|
|
||||||
msgid "There must not be a hierarchical loop. Please reload the page."
|
|
||||||
msgstr "No puede haber un círculo de hierarquías. Por favor recarque la página."
|
|
||||||
|
|
||||||
#: agenda/views.py:341
|
|
||||||
msgid "The agenda has been sorted."
|
|
||||||
msgstr "El programa ha sido ordenado."
|
|
||||||
|
|
||||||
#: assignments/models.py:164
|
|
||||||
msgid "Election"
|
|
||||||
msgstr "Elección"
|
|
||||||
|
|
||||||
#: assignments/serializers.py:31
|
|
||||||
msgid "Value for {} must be greater than 0"
|
|
||||||
msgstr "El valor de {} debe ser superior a 0"
|
|
||||||
|
|
||||||
#: assignments/serializers.py:149
|
|
||||||
#, python-format
|
|
||||||
msgid "You have to submit data for %d candidates."
|
|
||||||
msgstr "Usted tiene que enviar datos para %d candidatos."
|
|
||||||
|
|
||||||
#: assignments/serializers.py:153 motions/serializers.py:236
|
|
||||||
#, python-format
|
|
||||||
msgid "You have to submit data for %d vote values."
|
|
||||||
msgstr "Usted tiene que enviar datos para %d valores de voto."
|
|
||||||
|
|
||||||
#: assignments/serializers.py:157 motions/serializers.py:240
|
|
||||||
#, python-format
|
|
||||||
msgid "Vote value %s is invalid."
|
|
||||||
msgstr "El valor de voto %s no es válido."
|
|
||||||
|
|
||||||
#: assignments/views.py:66
|
|
||||||
msgid "You are already elected."
|
|
||||||
msgstr "Usted ya ha sido elegido."
|
|
||||||
|
|
||||||
#: assignments/views.py:76
|
|
||||||
msgid "You can not candidate to this election because it is finished."
|
|
||||||
msgstr "Usted no puede ser candidato para esta elección porque la elección ha terminado."
|
|
||||||
|
|
||||||
#: assignments/views.py:85
|
|
||||||
msgid "You were nominated successfully."
|
|
||||||
msgstr "Usted ha sido nombrado correctamente."
|
|
||||||
|
|
||||||
#: assignments/views.py:90
|
|
||||||
msgid ""
|
|
||||||
"You can not withdraw your candidature to this election because it is "
|
|
||||||
"finished."
|
|
||||||
msgstr "Usted no puede retirar su candidatura para esta elección porque ha terminado."
|
|
||||||
|
|
||||||
#: assignments/views.py:95
|
|
||||||
msgid "You are not a candidate of this election."
|
|
||||||
msgstr "Usted no es un candidato para esta elección."
|
|
||||||
|
|
||||||
#: assignments/views.py:97
|
|
||||||
msgid "You have withdrawn your candidature successfully."
|
|
||||||
msgstr "Usted ha retirado su candidatura con éxito."
|
|
||||||
|
|
||||||
#: assignments/views.py:106
|
|
||||||
#, python-format
|
|
||||||
msgid "Invalid data. Expected dictionary, got %s."
|
|
||||||
msgstr "Datos inválidos. Esperaba un diccionario, llegó %s."
|
|
||||||
|
|
||||||
#: assignments/views.py:112
|
|
||||||
msgid "Invalid data. Expected something like {\"user\": <id>}."
|
|
||||||
msgstr "Datos inválidos. Esperaba algo como {\"user\": <id>}."
|
|
||||||
|
|
||||||
#: assignments/views.py:116
|
|
||||||
#, python-format
|
|
||||||
msgid "Invalid data. User %d does not exist."
|
|
||||||
msgstr "Datos inválidos. El usuario %d no existe."
|
|
||||||
|
|
||||||
#: assignments/views.py:136
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is already elected."
|
|
||||||
msgstr "El usuario %s ya está elegido."
|
|
||||||
|
|
||||||
#: assignments/views.py:138
|
|
||||||
msgid "You can not nominate someone to this election because it is finished."
|
|
||||||
msgstr "No se puede nominar a alguien a esta elección porque ha terminado."
|
|
||||||
|
|
||||||
#: assignments/views.py:144
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is already nominated."
|
|
||||||
msgstr "El usuario %s ya está nominado."
|
|
||||||
|
|
||||||
#: assignments/views.py:149
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was nominated successfully."
|
|
||||||
msgstr "El usuario %s fue nominado correctamente."
|
|
||||||
|
|
||||||
#: assignments/views.py:156
|
|
||||||
msgid ""
|
|
||||||
"You can not delete someone's candidature to this election because it is "
|
|
||||||
"finished."
|
|
||||||
msgstr "No se puede eliminar la candidatura de alguien para esta elección porque ya ha terminado."
|
|
||||||
|
|
||||||
#: assignments/views.py:159
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s has no status in this election."
|
|
||||||
msgstr "El usuario %s no tiene estatus en esta elección."
|
|
||||||
|
|
||||||
#: assignments/views.py:161
|
|
||||||
#, python-format
|
|
||||||
msgid "Candidate %s was withdrawn successfully."
|
|
||||||
msgstr "%s candidato fue retirado con éxito."
|
|
||||||
|
|
||||||
#: assignments/views.py:173
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is not a candidate of this election."
|
|
||||||
msgstr "El usuario %s no es un candidato de esta elección."
|
|
||||||
|
|
||||||
#: assignments/views.py:175
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully elected."
|
|
||||||
msgstr "El usuario %s fue elegido con éxito."
|
|
||||||
|
|
||||||
#: assignments/views.py:179
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is not an elected candidate of this election."
|
|
||||||
msgstr "El usuario %s no es un candidato electo de esta elección."
|
|
||||||
|
|
||||||
#: assignments/views.py:182
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully unelected."
|
|
||||||
msgstr "La elección del usuario %s de deshizo correctamente."
|
|
||||||
|
|
||||||
#: assignments/views.py:192
|
|
||||||
msgid "Can not create ballot because there are no candidates."
|
|
||||||
msgstr "No se puede crear la votación porque no hay candidatos."
|
|
||||||
|
|
||||||
#: assignments/views.py:195
|
|
||||||
msgid "Ballot created successfully."
|
|
||||||
msgstr "Boleta creada correctamente."
|
|
||||||
|
|
||||||
#: assignments/views.py:210
|
|
||||||
msgid "users has to be a list of IDs."
|
|
||||||
msgstr "tiene que ser una lista de IDs."
|
|
||||||
|
|
||||||
#: assignments/views.py:237
|
|
||||||
msgid "Assignment related users successfully sorted."
|
|
||||||
msgstr "Los usuarios relacionados a este asignamento han sido ordenados correctamente."
|
|
||||||
|
|
||||||
#: core/config.py:50 core/config.py:76
|
|
||||||
msgid "The config variable {} was not found."
|
|
||||||
msgstr "La variable de configuración {} no fue encontrado."
|
|
||||||
|
|
||||||
#: core/config.py:85
|
|
||||||
#, python-format
|
|
||||||
msgid "Wrong datatype. Expected %(expected_type)s, got %(got_type)s."
|
|
||||||
msgstr "Tipo de datos incorrecto. Espera %(expected_type)s, obtuvo %(got_type)s."
|
|
||||||
|
|
||||||
#: core/config.py:95
|
|
||||||
msgid "Invalid input. Choice does not match."
|
|
||||||
msgstr "Entrada inválida. Selección no coincide."
|
|
||||||
|
|
||||||
#: core/config.py:105
|
|
||||||
msgid "motions_comments has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:111
|
|
||||||
msgid "Each id has to be an int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:114
|
|
||||||
msgid "Each id has to be greater then 0."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:118
|
|
||||||
msgid "Each commentsfield in motions_comments has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:120
|
|
||||||
msgid "A name and a public property have to be given."
|
|
||||||
msgstr "Un nombre y una propiedad pública tienen que ser transmitidos."
|
|
||||||
|
|
||||||
#: core/config.py:122
|
|
||||||
msgid "name has to be string."
|
|
||||||
msgstr "Name debe ser una cadena de caracteres."
|
|
||||||
|
|
||||||
#: core/config.py:124
|
|
||||||
msgid "public property has to be bool."
|
|
||||||
msgstr "La propiedad pública debe de ser booleano"
|
|
||||||
|
|
||||||
#: core/config.py:130
|
|
||||||
msgid "This has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:137 core/config.py:153
|
|
||||||
msgid "{} has to be given."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:139 core/config.py:155
|
|
||||||
msgid "{} has to be a string."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:143
|
|
||||||
msgid "Translations has to be a list."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:146
|
|
||||||
msgid "Every value has to be a dict, not {}."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:177
|
|
||||||
msgid "Too many values for config variables {} found."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:261
|
|
||||||
msgid "Invalid value for config attribute input_type."
|
|
||||||
msgstr "Valor inválido para el atributo input_type."
|
|
||||||
|
|
||||||
#: core/config.py:263
|
|
||||||
msgid ""
|
|
||||||
"Either config attribute 'choices' must not be None or 'input_type' must not "
|
|
||||||
"be 'choice'."
|
|
||||||
msgstr "El atributo 'choices' debe de ser None o 'input_type' no debe de ser 'choice'."
|
|
||||||
|
|
||||||
#: core/config.py:266
|
|
||||||
msgid ""
|
|
||||||
"Either config attribute 'choices' must be None or 'input_type' must be "
|
|
||||||
"'choice'."
|
|
||||||
msgstr "El atributo 'choices' debe ser Ninguno o 'input_type' debe ser 'choice'."
|
|
||||||
|
|
||||||
#: core/config.py:276
|
|
||||||
msgid "General"
|
|
||||||
msgstr "General"
|
|
||||||
|
|
||||||
#: core/views.py:277
|
|
||||||
msgid "The data has to be a list."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:280
|
|
||||||
msgid "All elements have to be dicts."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:420
|
|
||||||
msgid "The data has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:426
|
|
||||||
msgid "The id \"{}\" has to be int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:432
|
|
||||||
msgid "Prune has to be an object."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:435
|
|
||||||
msgid "The prune projector id has to be int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:440
|
|
||||||
msgid "The projector with id \"{}\" does not exist"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:444
|
|
||||||
msgid "Prune element has to be a dict or not given."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:772
|
|
||||||
msgid "All chat messages deleted successfully."
|
|
||||||
msgstr "Todos los mensajes de charla se han eliminado correctamente."
|
|
||||||
|
|
||||||
#: mediafiles/models.py:87
|
|
||||||
msgid "unknown"
|
|
||||||
msgstr "desconocido"
|
|
||||||
|
|
||||||
#: motions/models.py:190
|
|
||||||
msgid "Motion"
|
|
||||||
msgstr "Moción"
|
|
||||||
|
|
||||||
#: motions/models.py:744
|
|
||||||
msgid "new"
|
|
||||||
msgstr "nuevo"
|
|
||||||
|
|
||||||
#: motions/models.py:969
|
|
||||||
#, python-format
|
|
||||||
msgid "%(time_and_messages)s by %(person)s"
|
|
||||||
msgstr "%(time_and_messages)s de %(person)s"
|
|
||||||
|
|
||||||
#: motions/serializers.py:36
|
|
||||||
#, python-format
|
|
||||||
msgid "Workflow %(pk)d does not exist."
|
|
||||||
msgstr "Flujo %(pk)d no existe."
|
|
||||||
|
|
||||||
#: motions/signals.py:22
|
|
||||||
msgid "submitted"
|
|
||||||
msgstr "presentado"
|
|
||||||
|
|
||||||
#: motions/signals.py:27 motions/signals.py:60
|
|
||||||
msgid "accepted"
|
|
||||||
msgstr "aceptado"
|
|
||||||
|
|
||||||
#: motions/signals.py:32 motions/signals.py:66
|
|
||||||
msgid "rejected"
|
|
||||||
msgstr "rechazado"
|
|
||||||
|
|
||||||
#: motions/signals.py:37
|
|
||||||
msgid "not decided"
|
|
||||||
msgstr "no decidido"
|
|
||||||
|
|
||||||
#: motions/signals.py:47
|
|
||||||
msgid "published"
|
|
||||||
msgstr "publicado"
|
|
||||||
|
|
||||||
#: motions/signals.py:52 motions/views.py:300
|
|
||||||
msgid "permitted"
|
|
||||||
msgstr "permitido"
|
|
||||||
|
|
||||||
#: motions/signals.py:72
|
|
||||||
msgid "withdrawed"
|
|
||||||
msgstr "retirado"
|
|
||||||
|
|
||||||
#: motions/signals.py:77
|
|
||||||
msgid "adjourned"
|
|
||||||
msgstr "aplazado"
|
|
||||||
|
|
||||||
#: motions/signals.py:83
|
|
||||||
msgid "not concerned"
|
|
||||||
msgstr "no afectado"
|
|
||||||
|
|
||||||
#: motions/signals.py:89
|
|
||||||
msgid "refered to committee"
|
|
||||||
msgstr "remitido al comité"
|
|
||||||
|
|
||||||
#: motions/signals.py:95
|
|
||||||
msgid "needs review"
|
|
||||||
msgstr "necesita revisión"
|
|
||||||
|
|
||||||
#: motions/signals.py:100
|
|
||||||
msgid "rejected (not authorized)"
|
|
||||||
msgstr "rechazado (no autorizado)"
|
|
||||||
|
|
||||||
#: motions/views.py:110
|
|
||||||
msgid "The parent motion does not exist."
|
|
||||||
msgstr "La moción principal no existe."
|
|
||||||
|
|
||||||
#: motions/views.py:154
|
|
||||||
msgid "Motion created"
|
|
||||||
msgstr "Moción creada"
|
|
||||||
|
|
||||||
#: motions/views.py:256
|
|
||||||
msgid "Motion updated"
|
|
||||||
msgstr "Moción actualizada"
|
|
||||||
|
|
||||||
#: motions/views.py:260
|
|
||||||
msgid "All supporters removed"
|
|
||||||
msgstr "Todos los apoyadores fueron retirados"
|
|
||||||
|
|
||||||
#: motions/views.py:264
|
|
||||||
msgid "Comment {} updated"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:298 motions/views.py:310
|
|
||||||
msgid "Version"
|
|
||||||
msgstr "Versión"
|
|
||||||
|
|
||||||
#: motions/views.py:302
|
|
||||||
#, python-format
|
|
||||||
msgid "Version %d permitted successfully."
|
|
||||||
msgstr "Versión %d permitida correctamente."
|
|
||||||
|
|
||||||
#: motions/views.py:307
|
|
||||||
msgid "You can not delete the active version of a motion."
|
|
||||||
msgstr "No puede eliminar la versión activa de una moción."
|
|
||||||
|
|
||||||
#: motions/views.py:312
|
|
||||||
msgid "deleted"
|
|
||||||
msgstr "eliminado"
|
|
||||||
|
|
||||||
#: motions/views.py:314
|
|
||||||
#, python-format
|
|
||||||
msgid "Version %d deleted successfully."
|
|
||||||
msgstr "La versión %d se ha eliminado correctamente."
|
|
||||||
|
|
||||||
#: motions/views.py:337
|
|
||||||
msgid "You can not support this motion."
|
|
||||||
msgstr "Usted no puede apoyar esta propuesta."
|
|
||||||
|
|
||||||
#: motions/views.py:339
|
|
||||||
msgid "Motion supported"
|
|
||||||
msgstr "Moción apoyada"
|
|
||||||
|
|
||||||
#: motions/views.py:343
|
|
||||||
msgid "You have supported this motion successfully."
|
|
||||||
msgstr "Le ha apoyado esta moción correctamente."
|
|
||||||
|
|
||||||
#: motions/views.py:348
|
|
||||||
msgid "You can not unsupport this motion."
|
|
||||||
msgstr "No puede desapoyar esta moción."
|
|
||||||
|
|
||||||
#: motions/views.py:350
|
|
||||||
msgid "Motion unsupported"
|
|
||||||
msgstr "Moción desapoyada."
|
|
||||||
|
|
||||||
#: motions/views.py:351
|
|
||||||
msgid "You have unsupported this motion successfully."
|
|
||||||
msgstr "Usted desapoyó esta moción correctamente."
|
|
||||||
|
|
||||||
#: motions/views.py:374
|
|
||||||
msgid "Invalid data. State must be an integer."
|
|
||||||
msgstr "Datos inválidos. Estado debe ser un número entero."
|
|
||||||
|
|
||||||
#: motions/views.py:377
|
|
||||||
#, python-format
|
|
||||||
msgid "You can not set the state to %(state_id)d."
|
|
||||||
msgstr "No puede asignar el estado a %(state_id)d."
|
|
||||||
|
|
||||||
#: motions/views.py:385
|
|
||||||
#, python-format
|
|
||||||
msgid "The state of the motion was set to %s."
|
|
||||||
msgstr "El estado de la moción fue establecido en %s."
|
|
||||||
|
|
||||||
#: motions/views.py:389 motions/views.py:458 motions/views.py:726
|
|
||||||
msgid "State set to"
|
|
||||||
msgstr "Estado establecido en"
|
|
||||||
|
|
||||||
#: motions/views.py:413
|
|
||||||
msgid "Invalid data. Recommendation must be an integer."
|
|
||||||
msgstr "Datos inválidos. Recomendación debe de ser un número entero."
|
|
||||||
|
|
||||||
#: motions/views.py:417
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "You can not set the recommendation to {recommendation_state_id}."
|
|
||||||
msgstr "No puede asignar la recomendación a {recommendation_state_id}."
|
|
||||||
|
|
||||||
#: motions/views.py:427
|
|
||||||
#, python-format
|
|
||||||
msgid "The recommendation of the motion was set to %s."
|
|
||||||
msgstr "La recomendación de la moción fue establecido en %s."
|
|
||||||
|
|
||||||
#: motions/views.py:431
|
|
||||||
msgid "Recommendation set to"
|
|
||||||
msgstr "Recomendación establecido en"
|
|
||||||
|
|
||||||
#: motions/views.py:439
|
|
||||||
msgid "Cannot set an empty recommendation."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:479
|
|
||||||
msgid "Vote created"
|
|
||||||
msgstr "Voto creado"
|
|
||||||
|
|
||||||
#: motions/views.py:483
|
|
||||||
msgid "Vote created successfully."
|
|
||||||
msgstr "Voto creado correctamente."
|
|
||||||
|
|
||||||
#: motions/views.py:509
|
|
||||||
msgid "Vote updated"
|
|
||||||
msgstr "Voto actualizado"
|
|
||||||
|
|
||||||
#: motions/views.py:518
|
|
||||||
msgid "Vote deleted"
|
|
||||||
msgstr "Voto eliminado"
|
|
||||||
|
|
||||||
#: motions/views.py:652
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"Numbering aborted because the motion identifier \"%s\" already exists "
|
|
||||||
"outside of this category."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:675
|
|
||||||
msgid ""
|
|
||||||
"Error: At least one identifier of this category does already exist in "
|
|
||||||
"another category."
|
|
||||||
msgstr "Error: Al menos un identificador de esta categoría ya existe en otra categoría."
|
|
||||||
|
|
||||||
#: motions/views.py:680
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "All motions in category {category} numbered successfully."
|
|
||||||
msgstr "Todas mociones de la categoría {category} numeradas correctamente."
|
|
||||||
|
|
||||||
#: motions/views.py:731
|
|
||||||
msgid "Followed recommendations successfully."
|
|
||||||
msgstr "Las recomendaciones se han seguidos con éxito."
|
|
||||||
|
|
||||||
#: poll/models.py:194
|
|
||||||
msgid "majority"
|
|
||||||
msgstr "mayoría"
|
|
||||||
|
|
||||||
#: poll/models.py:196 poll/models.py:198
|
|
||||||
msgid "undocumented"
|
|
||||||
msgstr "Indocumentado"
|
|
||||||
|
|
||||||
#: poll/serializers.py:16
|
|
||||||
msgid "Value for {} must not be less than -2"
|
|
||||||
msgstr "El valor de {} no debe ser inferior a -2"
|
|
||||||
|
|
||||||
#: users/serializers.py:49
|
|
||||||
msgid ""
|
|
||||||
"The groups this user belongs to. A user will get all permissions granted to "
|
|
||||||
"each of his/her groups."
|
|
||||||
msgstr "Los grupos a las que pertenece este usuario. Un usuario obtendrá todos los permisos concedidos a cada uno de sus grupos."
|
|
||||||
|
|
||||||
#: users/serializers.py:72
|
|
||||||
msgid "Username, given name and surname can not all be empty."
|
|
||||||
msgstr "Nombre de usuario, nombre y apellido no todos pueden estar vacíos."
|
|
||||||
|
|
||||||
#: users/serializers.py:109
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "Incorrect value \"{value}\". Expected app_label.codename string."
|
|
||||||
msgstr "Valor incorrecto \"{value}\". Esperaba app_label.codename cadena."
|
|
||||||
|
|
||||||
#: users/serializers.py:110
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "Invalid permission \"{value}\". Object does not exist."
|
|
||||||
msgstr "Permiso inválido: \"{value}\". El objeto no existe."
|
|
||||||
|
|
||||||
#: users/views.py:91
|
|
||||||
msgid "You can not deactivate yourself."
|
|
||||||
msgstr "No puede desactivarse a sí mismo."
|
|
||||||
|
|
||||||
#: users/views.py:114
|
|
||||||
msgid "You can not delete yourself."
|
|
||||||
msgstr "No puede borrar a sí mismo."
|
|
||||||
|
|
||||||
#: users/views.py:131
|
|
||||||
msgid "Password successfully reset."
|
|
||||||
msgstr "Contraseña restablecida correctamente."
|
|
||||||
|
|
||||||
#: users/views.py:172
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{number} users successfully imported."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/views.py:410
|
|
||||||
msgid "Cookies have to be enabled to use OpenSlides."
|
|
||||||
msgstr "Tiene que permitir cookies para utilizar OpenSlides."
|
|
||||||
|
|
||||||
#: users/views.py:413
|
|
||||||
msgid "Username or password is not correct."
|
|
||||||
msgstr "Nombre de usuario o la contraseña no es correcta."
|
|
||||||
|
|
||||||
#: users/views.py:439
|
|
||||||
#, python-brace-format
|
|
||||||
msgid ""
|
|
||||||
"Installation was successfully. Use {username} and {password} for first "
|
|
||||||
"login. Important: Please change your password!"
|
|
||||||
msgstr "Instalación exitosa. Utilice {username} y {password} para el primer inicio de sesión. Importante: ¡Cambie su contraseña!"
|
|
||||||
|
|
||||||
#: users/views.py:462
|
|
||||||
msgid "You are not authenticated."
|
|
||||||
msgstr "Usted no está autenticado."
|
|
||||||
|
|
||||||
#: users/views.py:509
|
|
||||||
msgid "Old password does not match."
|
|
||||||
msgstr "La contraseña antigua no coincide."
|
|
Binary file not shown.
@ -1,673 +0,0 @@
|
|||||||
# Language file of OpenSlides used by Transifex:
|
|
||||||
# https://www.transifex.com/openslides/openslides/
|
|
||||||
# Copyright (C) 2011–2015 by OpenSlides team, see AUTHORS.
|
|
||||||
# This file is distributed under the same license as the OpenSlides package.
|
|
||||||
# Translators:
|
|
||||||
# Emanuel Schütze <emanuel.schuetze@intevation.de>, 2017
|
|
||||||
# Moira Brülisauer <moosline@savvy.ch>, 2015-2017
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: OpenSlides\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2018-05-23 16:13+0200\n"
|
|
||||||
"PO-Revision-Date: 2018-05-23 14:15+0000\n"
|
|
||||||
"Last-Translator: Emanuel Schütze <emanuel.schuetze@intevation.de>\n"
|
|
||||||
"Language-Team: French (http://www.transifex.com/openslides/openslides/language/fr/)\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Language: fr\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
|
||||||
|
|
||||||
#: agenda/models.py:206
|
|
||||||
msgid "Agenda item"
|
|
||||||
msgstr "Point de l'ordre du jour"
|
|
||||||
|
|
||||||
#: agenda/models.py:207
|
|
||||||
msgid "Hidden item"
|
|
||||||
msgstr "élément masqué"
|
|
||||||
|
|
||||||
#: agenda/models.py:356
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{user} is already on the list of speakers."
|
|
||||||
msgstr "{user} est déjà sur la liste des orateurs."
|
|
||||||
|
|
||||||
#: agenda/models.py:359
|
|
||||||
msgid "An anonymous user can not be on lists of speakers."
|
|
||||||
msgstr "Un utilisateur anonyme no peut pas être sur la liste des orateurs."
|
|
||||||
|
|
||||||
#: agenda/views.py:116
|
|
||||||
msgid "The list of speakers is closed."
|
|
||||||
msgstr "La liste des orateurs est fermée."
|
|
||||||
|
|
||||||
#: agenda/views.py:125 agenda/views.py:150
|
|
||||||
msgid "User does not exist."
|
|
||||||
msgstr "L'utilisateur n'existe pas."
|
|
||||||
|
|
||||||
#: agenda/views.py:133
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully added to the list of speakers."
|
|
||||||
msgstr "L'utilisateur %s a été ajouté avec succès à la liste des orateurs."
|
|
||||||
|
|
||||||
#: agenda/views.py:154
|
|
||||||
msgid "Marked has to be a bool."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:163
|
|
||||||
msgid "The user is not in the list of speakers."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:168
|
|
||||||
msgid "You are successfully marked the speaker."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:170
|
|
||||||
msgid "You are successfully unmarked the speaker."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:187
|
|
||||||
msgid "You are not on the list of speakers."
|
|
||||||
msgstr "Vous n'êtes pas sur la liste des orateurs."
|
|
||||||
|
|
||||||
#: agenda/views.py:190
|
|
||||||
msgid "You are successfully removed from the list of speakers."
|
|
||||||
msgstr "Vous avez été envelé à la liste des orateurs avec succès."
|
|
||||||
|
|
||||||
#: agenda/views.py:212
|
|
||||||
msgid "speakers have been removed from the list of speakers."
|
|
||||||
msgstr "Les orateurs on été envelé avec succès de la liste des orateurs."
|
|
||||||
|
|
||||||
#: agenda/views.py:214
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s has been removed from the list of speakers."
|
|
||||||
msgstr "L' utilisateur %s a été envelé avec succès de la liste des orateurs."
|
|
||||||
|
|
||||||
#: agenda/views.py:216
|
|
||||||
msgid "No speakers have been removed from the list of speakers."
|
|
||||||
msgstr "Aucun orateur a été envelé de la liste des orateurs."
|
|
||||||
|
|
||||||
#: agenda/views.py:236
|
|
||||||
msgid "The list of speakers is empty."
|
|
||||||
msgstr "La liste des orateurs est vide."
|
|
||||||
|
|
||||||
#: agenda/views.py:241
|
|
||||||
msgid "Speaker does not exist."
|
|
||||||
msgstr "Orateur n'existe pas."
|
|
||||||
|
|
||||||
#: agenda/views.py:243
|
|
||||||
msgid "User is now speaking."
|
|
||||||
msgstr "utilisateur est entrain de parler."
|
|
||||||
|
|
||||||
#: agenda/views.py:254
|
|
||||||
#, python-format
|
|
||||||
msgid "There is no one speaking at the moment according to %(item)s."
|
|
||||||
msgstr "Il n'y a pas un a parlé au moment selon %(item)s."
|
|
||||||
|
|
||||||
#: agenda/views.py:256
|
|
||||||
msgid "The speech is finished now."
|
|
||||||
msgstr "Le discours maintenant terminé."
|
|
||||||
|
|
||||||
#: agenda/views.py:275 agenda/views.py:287 assignments/views.py:222
|
|
||||||
msgid "Invalid data."
|
|
||||||
msgstr "Données invalides."
|
|
||||||
|
|
||||||
#: agenda/views.py:300
|
|
||||||
msgid "List of speakers successfully sorted."
|
|
||||||
msgstr "Liste des orateurs a été trié avec succès."
|
|
||||||
|
|
||||||
#: agenda/views.py:309
|
|
||||||
msgid "Numbering of agenda items is deactivated."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:312
|
|
||||||
msgid "The agenda has been numbered."
|
|
||||||
msgstr "L'ordre du jour a été numéroté."
|
|
||||||
|
|
||||||
#: agenda/views.py:337
|
|
||||||
msgid "There must not be a hierarchical loop. Please reload the page."
|
|
||||||
msgstr "Il doit y avoir aucune boucle hiérarchique. Veuillez recharger la page."
|
|
||||||
|
|
||||||
#: agenda/views.py:341
|
|
||||||
msgid "The agenda has been sorted."
|
|
||||||
msgstr "L'ordre du jour a été trié."
|
|
||||||
|
|
||||||
#: assignments/models.py:164
|
|
||||||
msgid "Election"
|
|
||||||
msgstr "Election"
|
|
||||||
|
|
||||||
#: assignments/serializers.py:31
|
|
||||||
msgid "Value for {} must be greater than 0"
|
|
||||||
msgstr "La valeur de {} doit être supérieure à 0"
|
|
||||||
|
|
||||||
#: assignments/serializers.py:149
|
|
||||||
#, python-format
|
|
||||||
msgid "You have to submit data for %d candidates."
|
|
||||||
msgstr "Vous devez soumettre des données pour %d candidats."
|
|
||||||
|
|
||||||
#: assignments/serializers.py:153 motions/serializers.py:236
|
|
||||||
#, python-format
|
|
||||||
msgid "You have to submit data for %d vote values."
|
|
||||||
msgstr "Vous devez soumettre des données pour les valeurs %d votes."
|
|
||||||
|
|
||||||
#: assignments/serializers.py:157 motions/serializers.py:240
|
|
||||||
#, python-format
|
|
||||||
msgid "Vote value %s is invalid."
|
|
||||||
msgstr "Valeur de vote %s est invalide."
|
|
||||||
|
|
||||||
#: assignments/views.py:66
|
|
||||||
msgid "You are already elected."
|
|
||||||
msgstr "Vous êtes déja elu."
|
|
||||||
|
|
||||||
#: assignments/views.py:76
|
|
||||||
msgid "You can not candidate to this election because it is finished."
|
|
||||||
msgstr "Vous ne pouvez pas vous présenter pour cette élection car elle terminée."
|
|
||||||
|
|
||||||
#: assignments/views.py:85
|
|
||||||
msgid "You were nominated successfully."
|
|
||||||
msgstr "Vous avez été nominé avec succès. "
|
|
||||||
|
|
||||||
#: assignments/views.py:90
|
|
||||||
msgid ""
|
|
||||||
"You can not withdraw your candidature to this election because it is "
|
|
||||||
"finished."
|
|
||||||
msgstr "Vous ne pouvez pas retirer votre candidature à cette élection car elle terminée."
|
|
||||||
|
|
||||||
#: assignments/views.py:95
|
|
||||||
msgid "You are not a candidate of this election."
|
|
||||||
msgstr "Vous n'êtes pas un candidat de cette élection."
|
|
||||||
|
|
||||||
#: assignments/views.py:97
|
|
||||||
msgid "You have withdrawn your candidature successfully."
|
|
||||||
msgstr "Vous avez retiré votre candidature avec succès."
|
|
||||||
|
|
||||||
#: assignments/views.py:106
|
|
||||||
#, python-format
|
|
||||||
msgid "Invalid data. Expected dictionary, got %s."
|
|
||||||
msgstr "Données invalides. Dictionnaire attendu, obtenu %s."
|
|
||||||
|
|
||||||
#: assignments/views.py:112
|
|
||||||
msgid "Invalid data. Expected something like {\"user\": <id>}."
|
|
||||||
msgstr "Données invalides. Attendu quelque chose comme {\"user\": <id>}."
|
|
||||||
|
|
||||||
#: assignments/views.py:116
|
|
||||||
#, python-format
|
|
||||||
msgid "Invalid data. User %d does not exist."
|
|
||||||
msgstr "Données invalides. L'utilisateur %d ne existe pas."
|
|
||||||
|
|
||||||
#: assignments/views.py:136
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is already elected."
|
|
||||||
msgstr "L'utilisateur %s est déja elu."
|
|
||||||
|
|
||||||
#: assignments/views.py:138
|
|
||||||
msgid "You can not nominate someone to this election because it is finished."
|
|
||||||
msgstr "Vous ne pouvez pas nommer quelqu'un pour cette élection, car elle terminée."
|
|
||||||
|
|
||||||
#: assignments/views.py:144
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is already nominated."
|
|
||||||
msgstr "L'utilisateur %s est déja nommé."
|
|
||||||
|
|
||||||
#: assignments/views.py:149
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was nominated successfully."
|
|
||||||
msgstr "Le candidat %s a été nommé avec succès. "
|
|
||||||
|
|
||||||
#: assignments/views.py:156
|
|
||||||
msgid ""
|
|
||||||
"You can not delete someone's candidature to this election because it is "
|
|
||||||
"finished."
|
|
||||||
msgstr "Vous ne pouvez pas supprimer la candidature de quelqu'un à cette élection, car il est terminé."
|
|
||||||
|
|
||||||
#: assignments/views.py:159
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s has no status in this election."
|
|
||||||
msgstr "L'utilisateur %s n'a pas de statut dans cette élection."
|
|
||||||
|
|
||||||
#: assignments/views.py:161
|
|
||||||
#, python-format
|
|
||||||
msgid "Candidate %s was withdrawn successfully."
|
|
||||||
msgstr "Le candidat %s a été rejeté avec succès."
|
|
||||||
|
|
||||||
#: assignments/views.py:173
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is not a candidate of this election."
|
|
||||||
msgstr "L'utilisateur %s n'est pas un candidat de cette élection."
|
|
||||||
|
|
||||||
#: assignments/views.py:175
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully elected."
|
|
||||||
msgstr "L'utilisateur %s a été élu avec succès."
|
|
||||||
|
|
||||||
#: assignments/views.py:179
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is not an elected candidate of this election."
|
|
||||||
msgstr "L'utilisateur %s n'est pas un candidat élu de cette élection."
|
|
||||||
|
|
||||||
#: assignments/views.py:182
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully unelected."
|
|
||||||
msgstr "L'utilisateur %s a été non élu avec succès."
|
|
||||||
|
|
||||||
#: assignments/views.py:192
|
|
||||||
msgid "Can not create ballot because there are no candidates."
|
|
||||||
msgstr "Vous ne pouvez pas créer des scrutins, car il n'y a pas de candidats."
|
|
||||||
|
|
||||||
#: assignments/views.py:195
|
|
||||||
msgid "Ballot created successfully."
|
|
||||||
msgstr "Le scrutin a été créé avec succès."
|
|
||||||
|
|
||||||
#: assignments/views.py:210
|
|
||||||
msgid "users has to be a list of IDs."
|
|
||||||
msgstr "Les utilisateurs doivent être une liste d'ID."
|
|
||||||
|
|
||||||
#: assignments/views.py:237
|
|
||||||
msgid "Assignment related users successfully sorted."
|
|
||||||
msgstr "Les candidats on été trié avec avec succès."
|
|
||||||
|
|
||||||
#: core/config.py:50 core/config.py:76
|
|
||||||
msgid "The config variable {} was not found."
|
|
||||||
msgstr "La variable de configuration {} n'a pas été trouvé."
|
|
||||||
|
|
||||||
#: core/config.py:85
|
|
||||||
#, python-format
|
|
||||||
msgid "Wrong datatype. Expected %(expected_type)s, got %(got_type)s."
|
|
||||||
msgstr "Type de données erronées. %(expected_type)s, obtenu %(got_type)s."
|
|
||||||
|
|
||||||
#: core/config.py:95
|
|
||||||
msgid "Invalid input. Choice does not match."
|
|
||||||
msgstr "Entrée invalide. Choix ne correspond pas."
|
|
||||||
|
|
||||||
#: core/config.py:105
|
|
||||||
msgid "motions_comments has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:111
|
|
||||||
msgid "Each id has to be an int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:114
|
|
||||||
msgid "Each id has to be greater then 0."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:118
|
|
||||||
msgid "Each commentsfield in motions_comments has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:120
|
|
||||||
msgid "A name and a public property have to be given."
|
|
||||||
msgstr "Un nom et un une propriété public doivent être donnés."
|
|
||||||
|
|
||||||
#: core/config.py:122
|
|
||||||
msgid "name has to be string."
|
|
||||||
msgstr "Nom doit être un string"
|
|
||||||
|
|
||||||
#: core/config.py:124
|
|
||||||
msgid "public property has to be bool."
|
|
||||||
msgstr "La propriété publique doit être bool."
|
|
||||||
|
|
||||||
#: core/config.py:130
|
|
||||||
msgid "This has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:137 core/config.py:153
|
|
||||||
msgid "{} has to be given."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:139 core/config.py:155
|
|
||||||
msgid "{} has to be a string."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:143
|
|
||||||
msgid "Translations has to be a list."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:146
|
|
||||||
msgid "Every value has to be a dict, not {}."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:177
|
|
||||||
msgid "Too many values for config variables {} found."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:261
|
|
||||||
msgid "Invalid value for config attribute input_type."
|
|
||||||
msgstr "Valeur incorrecte pour l'attribut de configuration input_type."
|
|
||||||
|
|
||||||
#: core/config.py:263
|
|
||||||
msgid ""
|
|
||||||
"Either config attribute 'choices' must not be None or 'input_type' must not "
|
|
||||||
"be 'choice'."
|
|
||||||
msgstr "Soit l'attribut de configuration 'choix' ne doit pas être aucun ou 'input_type' ne dois pas être 'choix'."
|
|
||||||
|
|
||||||
#: core/config.py:266
|
|
||||||
msgid ""
|
|
||||||
"Either config attribute 'choices' must be None or 'input_type' must be "
|
|
||||||
"'choice'."
|
|
||||||
msgstr "Soit l'attribut de configuration 'choix' ne doit pas être aucun ou 'input_type' ne doit être 'choix'."
|
|
||||||
|
|
||||||
#: core/config.py:276
|
|
||||||
msgid "General"
|
|
||||||
msgstr "Général"
|
|
||||||
|
|
||||||
#: core/views.py:277
|
|
||||||
msgid "The data has to be a list."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:280
|
|
||||||
msgid "All elements have to be dicts."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:420
|
|
||||||
msgid "The data has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:426
|
|
||||||
msgid "The id \"{}\" has to be int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:432
|
|
||||||
msgid "Prune has to be an object."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:435
|
|
||||||
msgid "The prune projector id has to be int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:440
|
|
||||||
msgid "The projector with id \"{}\" does not exist"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:444
|
|
||||||
msgid "Prune element has to be a dict or not given."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:772
|
|
||||||
msgid "All chat messages deleted successfully."
|
|
||||||
msgstr "Tous les messages du chat ont été supprimés avec succès."
|
|
||||||
|
|
||||||
#: mediafiles/models.py:87
|
|
||||||
msgid "unknown"
|
|
||||||
msgstr "inconnu"
|
|
||||||
|
|
||||||
#: motions/models.py:190
|
|
||||||
msgid "Motion"
|
|
||||||
msgstr "Motion"
|
|
||||||
|
|
||||||
#: motions/models.py:744
|
|
||||||
msgid "new"
|
|
||||||
msgstr "nouveau"
|
|
||||||
|
|
||||||
#: motions/models.py:969
|
|
||||||
#, python-format
|
|
||||||
msgid "%(time_and_messages)s by %(person)s"
|
|
||||||
msgstr "%(time_and_messages)s par %(person)s"
|
|
||||||
|
|
||||||
#: motions/serializers.py:36
|
|
||||||
#, python-format
|
|
||||||
msgid "Workflow %(pk)d does not exist."
|
|
||||||
msgstr "Flux de travail %(pk)d n'existe pas."
|
|
||||||
|
|
||||||
#: motions/signals.py:22
|
|
||||||
msgid "submitted"
|
|
||||||
msgstr "présenté"
|
|
||||||
|
|
||||||
#: motions/signals.py:27 motions/signals.py:60
|
|
||||||
msgid "accepted"
|
|
||||||
msgstr "accepté"
|
|
||||||
|
|
||||||
#: motions/signals.py:32 motions/signals.py:66
|
|
||||||
msgid "rejected"
|
|
||||||
msgstr "rejeté"
|
|
||||||
|
|
||||||
#: motions/signals.py:37
|
|
||||||
msgid "not decided"
|
|
||||||
msgstr "ne pas decidé"
|
|
||||||
|
|
||||||
#: motions/signals.py:47
|
|
||||||
msgid "published"
|
|
||||||
msgstr "publié"
|
|
||||||
|
|
||||||
#: motions/signals.py:52 motions/views.py:300
|
|
||||||
msgid "permitted"
|
|
||||||
msgstr "permis"
|
|
||||||
|
|
||||||
#: motions/signals.py:72
|
|
||||||
msgid "withdrawed"
|
|
||||||
msgstr "retiré"
|
|
||||||
|
|
||||||
#: motions/signals.py:77
|
|
||||||
msgid "adjourned"
|
|
||||||
msgstr "ajourné"
|
|
||||||
|
|
||||||
#: motions/signals.py:83
|
|
||||||
msgid "not concerned"
|
|
||||||
msgstr "non concerné"
|
|
||||||
|
|
||||||
#: motions/signals.py:89
|
|
||||||
msgid "refered to committee"
|
|
||||||
msgstr "renvoyé à un comité."
|
|
||||||
|
|
||||||
#: motions/signals.py:95
|
|
||||||
msgid "needs review"
|
|
||||||
msgstr "doit être revu"
|
|
||||||
|
|
||||||
#: motions/signals.py:100
|
|
||||||
msgid "rejected (not authorized)"
|
|
||||||
msgstr "Rejeté (non autorisé)"
|
|
||||||
|
|
||||||
#: motions/views.py:110
|
|
||||||
msgid "The parent motion does not exist."
|
|
||||||
msgstr "La motion parental n'existe pas."
|
|
||||||
|
|
||||||
#: motions/views.py:154
|
|
||||||
msgid "Motion created"
|
|
||||||
msgstr "Motion créé"
|
|
||||||
|
|
||||||
#: motions/views.py:256
|
|
||||||
msgid "Motion updated"
|
|
||||||
msgstr "motion mise à jour"
|
|
||||||
|
|
||||||
#: motions/views.py:260
|
|
||||||
msgid "All supporters removed"
|
|
||||||
msgstr "Tous les partisans supprimés"
|
|
||||||
|
|
||||||
#: motions/views.py:264
|
|
||||||
msgid "Comment {} updated"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:298 motions/views.py:310
|
|
||||||
msgid "Version"
|
|
||||||
msgstr "Version"
|
|
||||||
|
|
||||||
#: motions/views.py:302
|
|
||||||
#, python-format
|
|
||||||
msgid "Version %d permitted successfully."
|
|
||||||
msgstr "Version %d a été autorisé avec succes."
|
|
||||||
|
|
||||||
#: motions/views.py:307
|
|
||||||
msgid "You can not delete the active version of a motion."
|
|
||||||
msgstr "Vous ne pouvez pas suprimer la version active de cette motion. "
|
|
||||||
|
|
||||||
#: motions/views.py:312
|
|
||||||
msgid "deleted"
|
|
||||||
msgstr "Suprimé"
|
|
||||||
|
|
||||||
#: motions/views.py:314
|
|
||||||
#, python-format
|
|
||||||
msgid "Version %d deleted successfully."
|
|
||||||
msgstr "Version %d a été suprimé avec succes."
|
|
||||||
|
|
||||||
#: motions/views.py:337
|
|
||||||
msgid "You can not support this motion."
|
|
||||||
msgstr "Vous ne pouvez pas soutenir cette motion. "
|
|
||||||
|
|
||||||
#: motions/views.py:339
|
|
||||||
msgid "Motion supported"
|
|
||||||
msgstr "Motion soutenu"
|
|
||||||
|
|
||||||
#: motions/views.py:343
|
|
||||||
msgid "You have supported this motion successfully."
|
|
||||||
msgstr "Vous soutenez maintenant cette motion, vous avez été ajouté avec succès."
|
|
||||||
|
|
||||||
#: motions/views.py:348
|
|
||||||
msgid "You can not unsupport this motion."
|
|
||||||
msgstr "Vous ne pouvez pas retirer votre soutien pour cette motion. "
|
|
||||||
|
|
||||||
#: motions/views.py:350
|
|
||||||
msgid "Motion unsupported"
|
|
||||||
msgstr "Motion ne plus soutenue"
|
|
||||||
|
|
||||||
#: motions/views.py:351
|
|
||||||
msgid "You have unsupported this motion successfully."
|
|
||||||
msgstr "Vous avez retiré votre soutien pour cette motion avec succès."
|
|
||||||
|
|
||||||
#: motions/views.py:374
|
|
||||||
msgid "Invalid data. State must be an integer."
|
|
||||||
msgstr "Données invalides. Le statut doit être intègre."
|
|
||||||
|
|
||||||
#: motions/views.py:377
|
|
||||||
#, python-format
|
|
||||||
msgid "You can not set the state to %(state_id)d."
|
|
||||||
msgstr "Vous ne pouvez pas fixé le statut à %(state_id)d."
|
|
||||||
|
|
||||||
#: motions/views.py:385
|
|
||||||
#, python-format
|
|
||||||
msgid "The state of the motion was set to %s."
|
|
||||||
msgstr "Le statut de la motion a été fixé à %s."
|
|
||||||
|
|
||||||
#: motions/views.py:389 motions/views.py:458 motions/views.py:726
|
|
||||||
msgid "State set to"
|
|
||||||
msgstr "Changer le statut à"
|
|
||||||
|
|
||||||
#: motions/views.py:413
|
|
||||||
msgid "Invalid data. Recommendation must be an integer."
|
|
||||||
msgstr "Données invalides. La recommandation doit être un entier."
|
|
||||||
|
|
||||||
#: motions/views.py:417
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "You can not set the recommendation to {recommendation_state_id}."
|
|
||||||
msgstr "Vous ne pouvez pas définir la recommandation à {recommendation_state_id}."
|
|
||||||
|
|
||||||
#: motions/views.py:427
|
|
||||||
#, python-format
|
|
||||||
msgid "The recommendation of the motion was set to %s."
|
|
||||||
msgstr "La recommandation de la motion a été fixée à %s."
|
|
||||||
|
|
||||||
#: motions/views.py:431
|
|
||||||
msgid "Recommendation set to"
|
|
||||||
msgstr "Recommandation définie à"
|
|
||||||
|
|
||||||
#: motions/views.py:439
|
|
||||||
msgid "Cannot set an empty recommendation."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:479
|
|
||||||
msgid "Vote created"
|
|
||||||
msgstr "Votation a été créé"
|
|
||||||
|
|
||||||
#: motions/views.py:483
|
|
||||||
msgid "Vote created successfully."
|
|
||||||
msgstr "La votation a été créé avec succès."
|
|
||||||
|
|
||||||
#: motions/views.py:509
|
|
||||||
msgid "Vote updated"
|
|
||||||
msgstr "Votation a été mis à jour"
|
|
||||||
|
|
||||||
#: motions/views.py:518
|
|
||||||
msgid "Vote deleted"
|
|
||||||
msgstr "La votation a été supprimée."
|
|
||||||
|
|
||||||
#: motions/views.py:652
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"Numbering aborted because the motion identifier \"%s\" already exists "
|
|
||||||
"outside of this category."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:675
|
|
||||||
msgid ""
|
|
||||||
"Error: At least one identifier of this category does already exist in "
|
|
||||||
"another category."
|
|
||||||
msgstr "Erreur: Au moins un identifiant de cette catégorie existe déjà dans une autre catégorie."
|
|
||||||
|
|
||||||
#: motions/views.py:680
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "All motions in category {category} numbered successfully."
|
|
||||||
msgstr "Toutes les motions de la catégorie {category} ont été numérotées avec succès."
|
|
||||||
|
|
||||||
#: motions/views.py:731
|
|
||||||
msgid "Followed recommendations successfully."
|
|
||||||
msgstr "Suivi des recommandations avec succès."
|
|
||||||
|
|
||||||
#: poll/models.py:194
|
|
||||||
msgid "majority"
|
|
||||||
msgstr "majorité"
|
|
||||||
|
|
||||||
#: poll/models.py:196 poll/models.py:198
|
|
||||||
msgid "undocumented"
|
|
||||||
msgstr "non documenté"
|
|
||||||
|
|
||||||
#: poll/serializers.py:16
|
|
||||||
msgid "Value for {} must not be less than -2"
|
|
||||||
msgstr "La valeur pour {} ne doit pas être inférieure à -2"
|
|
||||||
|
|
||||||
#: users/serializers.py:49
|
|
||||||
msgid ""
|
|
||||||
"The groups this user belongs to. A user will get all permissions granted to "
|
|
||||||
"each of his/her groups."
|
|
||||||
msgstr "Les groupes auxquels cet utilisateur appartient. Un utilisateur obtiendra toutes les autorisations accordées à chacun de ses groupes."
|
|
||||||
|
|
||||||
#: users/serializers.py:72
|
|
||||||
msgid "Username, given name and surname can not all be empty."
|
|
||||||
msgstr "Nom d'utilisateur, prénom et nom ne peuvent pas tous être vides."
|
|
||||||
|
|
||||||
#: users/serializers.py:109
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "Incorrect value \"{value}\". Expected app_label.codename string."
|
|
||||||
msgstr "Valeur incorrecte \"{value}\". Attendu sous app_label.codename string."
|
|
||||||
|
|
||||||
#: users/serializers.py:110
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "Invalid permission \"{value}\". Object does not exist."
|
|
||||||
msgstr "Autorisation non valable \"{value}\". L'object n'existe pas."
|
|
||||||
|
|
||||||
#: users/views.py:91
|
|
||||||
msgid "You can not deactivate yourself."
|
|
||||||
msgstr "Vous ne pouvez pas vous désactiver vous-même."
|
|
||||||
|
|
||||||
#: users/views.py:114
|
|
||||||
msgid "You can not delete yourself."
|
|
||||||
msgstr "Vous ne pouvez pas vous suprimer vous même."
|
|
||||||
|
|
||||||
#: users/views.py:131
|
|
||||||
msgid "Password successfully reset."
|
|
||||||
msgstr "Le mot de passe a été réinitialisé avec succès."
|
|
||||||
|
|
||||||
#: users/views.py:172
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{number} users successfully imported."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/views.py:410
|
|
||||||
msgid "Cookies have to be enabled to use OpenSlides."
|
|
||||||
msgstr "Les cookies doivent être activés pour utiliser OpenSlides."
|
|
||||||
|
|
||||||
#: users/views.py:413
|
|
||||||
msgid "Username or password is not correct."
|
|
||||||
msgstr "Nom d'utilisateur ou mot de passe n'est pas correcte."
|
|
||||||
|
|
||||||
#: users/views.py:439
|
|
||||||
#, python-brace-format
|
|
||||||
msgid ""
|
|
||||||
"Installation was successfully. Use {username} and {password} for first "
|
|
||||||
"login. Important: Please change your password!"
|
|
||||||
msgstr "L'installation a été terminé avec succès. Utilisez {username} et {password} pour la première connexion. Important: S'il vous plaît changer votre mot de passe!"
|
|
||||||
|
|
||||||
#: users/views.py:462
|
|
||||||
msgid "You are not authenticated."
|
|
||||||
msgstr "Vous n'êtes pas authentifié."
|
|
||||||
|
|
||||||
#: users/views.py:509
|
|
||||||
msgid "Old password does not match."
|
|
||||||
msgstr "L'ancien mot de passe ne correspond pas."
|
|
Binary file not shown.
@ -1,672 +0,0 @@
|
|||||||
# Language file of OpenSlides used by Transifex:
|
|
||||||
# https://www.transifex.com/openslides/openslides/
|
|
||||||
# Copyright (C) 2011–2015 by OpenSlides team, see AUTHORS.
|
|
||||||
# This file is distributed under the same license as the OpenSlides package.
|
|
||||||
# Translators:
|
|
||||||
# Marco A.G.Pinto <marcoagpinto@sapo.pt>, 2016-2017
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: OpenSlides\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2018-05-23 16:13+0200\n"
|
|
||||||
"PO-Revision-Date: 2018-05-23 14:15+0000\n"
|
|
||||||
"Last-Translator: Emanuel Schütze <emanuel.schuetze@intevation.de>\n"
|
|
||||||
"Language-Team: Portuguese (Portugal) (http://www.transifex.com/openslides/openslides/language/pt_PT/)\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Language: pt_PT\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: agenda/models.py:206
|
|
||||||
msgid "Agenda item"
|
|
||||||
msgstr "Item da agenda"
|
|
||||||
|
|
||||||
#: agenda/models.py:207
|
|
||||||
msgid "Hidden item"
|
|
||||||
msgstr "Item oculto"
|
|
||||||
|
|
||||||
#: agenda/models.py:356
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{user} is already on the list of speakers."
|
|
||||||
msgstr "{user} já está na lista de oradores."
|
|
||||||
|
|
||||||
#: agenda/models.py:359
|
|
||||||
msgid "An anonymous user can not be on lists of speakers."
|
|
||||||
msgstr "Um utilizador anónimo não pode estar em listas de oradores."
|
|
||||||
|
|
||||||
#: agenda/views.py:116
|
|
||||||
msgid "The list of speakers is closed."
|
|
||||||
msgstr "A lista de oradores está fechada."
|
|
||||||
|
|
||||||
#: agenda/views.py:125 agenda/views.py:150
|
|
||||||
msgid "User does not exist."
|
|
||||||
msgstr "Utilizador não existe."
|
|
||||||
|
|
||||||
#: agenda/views.py:133
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully added to the list of speakers."
|
|
||||||
msgstr "Utilizador %s adicionado com sucesso à lista de oradores."
|
|
||||||
|
|
||||||
#: agenda/views.py:154
|
|
||||||
msgid "Marked has to be a bool."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:163
|
|
||||||
msgid "The user is not in the list of speakers."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:168
|
|
||||||
msgid "You are successfully marked the speaker."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:170
|
|
||||||
msgid "You are successfully unmarked the speaker."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:187
|
|
||||||
msgid "You are not on the list of speakers."
|
|
||||||
msgstr "Não estás na lista de oradores."
|
|
||||||
|
|
||||||
#: agenda/views.py:190
|
|
||||||
msgid "You are successfully removed from the list of speakers."
|
|
||||||
msgstr "Foste removido com sucesso da lista de oradores."
|
|
||||||
|
|
||||||
#: agenda/views.py:212
|
|
||||||
msgid "speakers have been removed from the list of speakers."
|
|
||||||
msgstr "oradores foram removidos da lista de oradores."
|
|
||||||
|
|
||||||
#: agenda/views.py:214
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s has been removed from the list of speakers."
|
|
||||||
msgstr "Utilizador %s foi removido da lista de oradores."
|
|
||||||
|
|
||||||
#: agenda/views.py:216
|
|
||||||
msgid "No speakers have been removed from the list of speakers."
|
|
||||||
msgstr "Nenhuns oradores foram removidos da lista de oradores."
|
|
||||||
|
|
||||||
#: agenda/views.py:236
|
|
||||||
msgid "The list of speakers is empty."
|
|
||||||
msgstr "A lista de oradores está vazia."
|
|
||||||
|
|
||||||
#: agenda/views.py:241
|
|
||||||
msgid "Speaker does not exist."
|
|
||||||
msgstr "Orador não existe."
|
|
||||||
|
|
||||||
#: agenda/views.py:243
|
|
||||||
msgid "User is now speaking."
|
|
||||||
msgstr "Utilizador está agora a discursar."
|
|
||||||
|
|
||||||
#: agenda/views.py:254
|
|
||||||
#, python-format
|
|
||||||
msgid "There is no one speaking at the moment according to %(item)s."
|
|
||||||
msgstr "Não há ninguém a discursar no momento, de acordo com %(item)s."
|
|
||||||
|
|
||||||
#: agenda/views.py:256
|
|
||||||
msgid "The speech is finished now."
|
|
||||||
msgstr "O discurso está terminado agora."
|
|
||||||
|
|
||||||
#: agenda/views.py:275 agenda/views.py:287 assignments/views.py:222
|
|
||||||
msgid "Invalid data."
|
|
||||||
msgstr "Dados inválidos."
|
|
||||||
|
|
||||||
#: agenda/views.py:300
|
|
||||||
msgid "List of speakers successfully sorted."
|
|
||||||
msgstr "Lista de oradores ordenada com sucesso."
|
|
||||||
|
|
||||||
#: agenda/views.py:309
|
|
||||||
msgid "Numbering of agenda items is deactivated."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:312
|
|
||||||
msgid "The agenda has been numbered."
|
|
||||||
msgstr "A agenda foi numerada."
|
|
||||||
|
|
||||||
#: agenda/views.py:337
|
|
||||||
msgid "There must not be a hierarchical loop. Please reload the page."
|
|
||||||
msgstr "Não deve haver um loop hierárquico. Por favor recarrega a página."
|
|
||||||
|
|
||||||
#: agenda/views.py:341
|
|
||||||
msgid "The agenda has been sorted."
|
|
||||||
msgstr "A agenda foi ordenada."
|
|
||||||
|
|
||||||
#: assignments/models.py:164
|
|
||||||
msgid "Election"
|
|
||||||
msgstr "Eleição"
|
|
||||||
|
|
||||||
#: assignments/serializers.py:31
|
|
||||||
msgid "Value for {} must be greater than 0"
|
|
||||||
msgstr "O valor para {} deve ser maior que 0"
|
|
||||||
|
|
||||||
#: assignments/serializers.py:149
|
|
||||||
#, python-format
|
|
||||||
msgid "You have to submit data for %d candidates."
|
|
||||||
msgstr "Tens de submeter dados para %d candidatos."
|
|
||||||
|
|
||||||
#: assignments/serializers.py:153 motions/serializers.py:236
|
|
||||||
#, python-format
|
|
||||||
msgid "You have to submit data for %d vote values."
|
|
||||||
msgstr "Tens de submeter dados para %d valores de voto."
|
|
||||||
|
|
||||||
#: assignments/serializers.py:157 motions/serializers.py:240
|
|
||||||
#, python-format
|
|
||||||
msgid "Vote value %s is invalid."
|
|
||||||
msgstr "O valor de voto %s é inválido."
|
|
||||||
|
|
||||||
#: assignments/views.py:66
|
|
||||||
msgid "You are already elected."
|
|
||||||
msgstr "Já estás eleito."
|
|
||||||
|
|
||||||
#: assignments/views.py:76
|
|
||||||
msgid "You can not candidate to this election because it is finished."
|
|
||||||
msgstr "Não podes candidatar-te a esta eleição porque ela está terminada."
|
|
||||||
|
|
||||||
#: assignments/views.py:85
|
|
||||||
msgid "You were nominated successfully."
|
|
||||||
msgstr "Foste nomeado com sucesso."
|
|
||||||
|
|
||||||
#: assignments/views.py:90
|
|
||||||
msgid ""
|
|
||||||
"You can not withdraw your candidature to this election because it is "
|
|
||||||
"finished."
|
|
||||||
msgstr "Não podes retirar a tua candidatura a esta eleição porque ela está terminada."
|
|
||||||
|
|
||||||
#: assignments/views.py:95
|
|
||||||
msgid "You are not a candidate of this election."
|
|
||||||
msgstr "Não és candidato desta eleição."
|
|
||||||
|
|
||||||
#: assignments/views.py:97
|
|
||||||
msgid "You have withdrawn your candidature successfully."
|
|
||||||
msgstr "Retiraste a tua candidatura com sucesso."
|
|
||||||
|
|
||||||
#: assignments/views.py:106
|
|
||||||
#, python-format
|
|
||||||
msgid "Invalid data. Expected dictionary, got %s."
|
|
||||||
msgstr "Dados inválidos. Dicionário esperado, obteve-se %s."
|
|
||||||
|
|
||||||
#: assignments/views.py:112
|
|
||||||
msgid "Invalid data. Expected something like {\"user\": <id>}."
|
|
||||||
msgstr "Dados inválidos. Esperava-se algo como {\"utilizador\": <id>}."
|
|
||||||
|
|
||||||
#: assignments/views.py:116
|
|
||||||
#, python-format
|
|
||||||
msgid "Invalid data. User %d does not exist."
|
|
||||||
msgstr "Dados inválidos. Utilizador %d não existe."
|
|
||||||
|
|
||||||
#: assignments/views.py:136
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is already elected."
|
|
||||||
msgstr "O utilizador %s já está eleito."
|
|
||||||
|
|
||||||
#: assignments/views.py:138
|
|
||||||
msgid "You can not nominate someone to this election because it is finished."
|
|
||||||
msgstr "Não podes nomear alguém para esta eleição porque ela está terminada."
|
|
||||||
|
|
||||||
#: assignments/views.py:144
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is already nominated."
|
|
||||||
msgstr "O utilizador %s já está nomeado."
|
|
||||||
|
|
||||||
#: assignments/views.py:149
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was nominated successfully."
|
|
||||||
msgstr "O utilizador %s foi nomeado com sucesso."
|
|
||||||
|
|
||||||
#: assignments/views.py:156
|
|
||||||
msgid ""
|
|
||||||
"You can not delete someone's candidature to this election because it is "
|
|
||||||
"finished."
|
|
||||||
msgstr "Não podes excluir a candidatura de alguém a esta eleição porque ela está terminada."
|
|
||||||
|
|
||||||
#: assignments/views.py:159
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s has no status in this election."
|
|
||||||
msgstr "O utilizador %s não tem status nesta eleição."
|
|
||||||
|
|
||||||
#: assignments/views.py:161
|
|
||||||
#, python-format
|
|
||||||
msgid "Candidate %s was withdrawn successfully."
|
|
||||||
msgstr "O candidato %s foi retirado com sucesso."
|
|
||||||
|
|
||||||
#: assignments/views.py:173
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is not a candidate of this election."
|
|
||||||
msgstr "O utilizador %s não é um candidato desta eleição."
|
|
||||||
|
|
||||||
#: assignments/views.py:175
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully elected."
|
|
||||||
msgstr "O utilizador %s foi eleito com sucesso."
|
|
||||||
|
|
||||||
#: assignments/views.py:179
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is not an elected candidate of this election."
|
|
||||||
msgstr "O utilizador %s não é um candidato eleito desta eleição."
|
|
||||||
|
|
||||||
#: assignments/views.py:182
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully unelected."
|
|
||||||
msgstr "O utilizador %s foi não eleito com sucesso."
|
|
||||||
|
|
||||||
#: assignments/views.py:192
|
|
||||||
msgid "Can not create ballot because there are no candidates."
|
|
||||||
msgstr "Não é possível criar votação porque não há candidatos."
|
|
||||||
|
|
||||||
#: assignments/views.py:195
|
|
||||||
msgid "Ballot created successfully."
|
|
||||||
msgstr "Votação criada com sucesso."
|
|
||||||
|
|
||||||
#: assignments/views.py:210
|
|
||||||
msgid "users has to be a list of IDs."
|
|
||||||
msgstr "utilizadores tem que ser uma lista de IDs."
|
|
||||||
|
|
||||||
#: assignments/views.py:237
|
|
||||||
msgid "Assignment related users successfully sorted."
|
|
||||||
msgstr "Os utilizadores relacionados com a tarefa foram ordenados com sucesso."
|
|
||||||
|
|
||||||
#: core/config.py:50 core/config.py:76
|
|
||||||
msgid "The config variable {} was not found."
|
|
||||||
msgstr "A variável de configuração {} não foi encontrada."
|
|
||||||
|
|
||||||
#: core/config.py:85
|
|
||||||
#, python-format
|
|
||||||
msgid "Wrong datatype. Expected %(expected_type)s, got %(got_type)s."
|
|
||||||
msgstr "Tipo de dados errado. Esperava-se %(expected_type)s, obteu-se %(got_type)s."
|
|
||||||
|
|
||||||
#: core/config.py:95
|
|
||||||
msgid "Invalid input. Choice does not match."
|
|
||||||
msgstr "Entrada inválida. A escolha não coincide."
|
|
||||||
|
|
||||||
#: core/config.py:105
|
|
||||||
msgid "motions_comments has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:111
|
|
||||||
msgid "Each id has to be an int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:114
|
|
||||||
msgid "Each id has to be greater then 0."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:118
|
|
||||||
msgid "Each commentsfield in motions_comments has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:120
|
|
||||||
msgid "A name and a public property have to be given."
|
|
||||||
msgstr "É necessário um nome e uma propriedade pública."
|
|
||||||
|
|
||||||
#: core/config.py:122
|
|
||||||
msgid "name has to be string."
|
|
||||||
msgstr "o nome tem de ser uma string."
|
|
||||||
|
|
||||||
#: core/config.py:124
|
|
||||||
msgid "public property has to be bool."
|
|
||||||
msgstr "a propriedade pública tem de ser booleano."
|
|
||||||
|
|
||||||
#: core/config.py:130
|
|
||||||
msgid "This has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:137 core/config.py:153
|
|
||||||
msgid "{} has to be given."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:139 core/config.py:155
|
|
||||||
msgid "{} has to be a string."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:143
|
|
||||||
msgid "Translations has to be a list."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:146
|
|
||||||
msgid "Every value has to be a dict, not {}."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:177
|
|
||||||
msgid "Too many values for config variables {} found."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:261
|
|
||||||
msgid "Invalid value for config attribute input_type."
|
|
||||||
msgstr "Valor inválido para atributo de configuração input_type."
|
|
||||||
|
|
||||||
#: core/config.py:263
|
|
||||||
msgid ""
|
|
||||||
"Either config attribute 'choices' must not be None or 'input_type' must not "
|
|
||||||
"be 'choice'."
|
|
||||||
msgstr "Qualquer atributo de configuração 'choices' não pode ser None ou 'input_type' não pode ser 'choice'."
|
|
||||||
|
|
||||||
#: core/config.py:266
|
|
||||||
msgid ""
|
|
||||||
"Either config attribute 'choices' must be None or 'input_type' must be "
|
|
||||||
"'choice'."
|
|
||||||
msgstr "Qualquer atributo de configuração 'choices' deve ser None ou 'input_type' deve ser 'choice'."
|
|
||||||
|
|
||||||
#: core/config.py:276
|
|
||||||
msgid "General"
|
|
||||||
msgstr "Geral"
|
|
||||||
|
|
||||||
#: core/views.py:277
|
|
||||||
msgid "The data has to be a list."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:280
|
|
||||||
msgid "All elements have to be dicts."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:420
|
|
||||||
msgid "The data has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:426
|
|
||||||
msgid "The id \"{}\" has to be int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:432
|
|
||||||
msgid "Prune has to be an object."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:435
|
|
||||||
msgid "The prune projector id has to be int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:440
|
|
||||||
msgid "The projector with id \"{}\" does not exist"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:444
|
|
||||||
msgid "Prune element has to be a dict or not given."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:772
|
|
||||||
msgid "All chat messages deleted successfully."
|
|
||||||
msgstr "Todas as mensagens de chat apagadas com sucesso."
|
|
||||||
|
|
||||||
#: mediafiles/models.py:87
|
|
||||||
msgid "unknown"
|
|
||||||
msgstr "desconhecido"
|
|
||||||
|
|
||||||
#: motions/models.py:190
|
|
||||||
msgid "Motion"
|
|
||||||
msgstr "Moção"
|
|
||||||
|
|
||||||
#: motions/models.py:744
|
|
||||||
msgid "new"
|
|
||||||
msgstr "novo"
|
|
||||||
|
|
||||||
#: motions/models.py:969
|
|
||||||
#, python-format
|
|
||||||
msgid "%(time_and_messages)s by %(person)s"
|
|
||||||
msgstr "%(time_and_messages)s por %(person)s"
|
|
||||||
|
|
||||||
#: motions/serializers.py:36
|
|
||||||
#, python-format
|
|
||||||
msgid "Workflow %(pk)d does not exist."
|
|
||||||
msgstr "Fluxo de trabalho %(pk)d não existe."
|
|
||||||
|
|
||||||
#: motions/signals.py:22
|
|
||||||
msgid "submitted"
|
|
||||||
msgstr "submetido"
|
|
||||||
|
|
||||||
#: motions/signals.py:27 motions/signals.py:60
|
|
||||||
msgid "accepted"
|
|
||||||
msgstr "aceite"
|
|
||||||
|
|
||||||
#: motions/signals.py:32 motions/signals.py:66
|
|
||||||
msgid "rejected"
|
|
||||||
msgstr "rejeitado"
|
|
||||||
|
|
||||||
#: motions/signals.py:37
|
|
||||||
msgid "not decided"
|
|
||||||
msgstr "não decidido"
|
|
||||||
|
|
||||||
#: motions/signals.py:47
|
|
||||||
msgid "published"
|
|
||||||
msgstr "publicado"
|
|
||||||
|
|
||||||
#: motions/signals.py:52 motions/views.py:300
|
|
||||||
msgid "permitted"
|
|
||||||
msgstr "permitido"
|
|
||||||
|
|
||||||
#: motions/signals.py:72
|
|
||||||
msgid "withdrawed"
|
|
||||||
msgstr "retirado"
|
|
||||||
|
|
||||||
#: motions/signals.py:77
|
|
||||||
msgid "adjourned"
|
|
||||||
msgstr "adiado"
|
|
||||||
|
|
||||||
#: motions/signals.py:83
|
|
||||||
msgid "not concerned"
|
|
||||||
msgstr "não preocupado"
|
|
||||||
|
|
||||||
#: motions/signals.py:89
|
|
||||||
msgid "refered to committee"
|
|
||||||
msgstr "referida à comissão"
|
|
||||||
|
|
||||||
#: motions/signals.py:95
|
|
||||||
msgid "needs review"
|
|
||||||
msgstr "necessita de revisão"
|
|
||||||
|
|
||||||
#: motions/signals.py:100
|
|
||||||
msgid "rejected (not authorized)"
|
|
||||||
msgstr "rejeitado (não autorizado)"
|
|
||||||
|
|
||||||
#: motions/views.py:110
|
|
||||||
msgid "The parent motion does not exist."
|
|
||||||
msgstr "A moção pai não existe."
|
|
||||||
|
|
||||||
#: motions/views.py:154
|
|
||||||
msgid "Motion created"
|
|
||||||
msgstr "Moção criada"
|
|
||||||
|
|
||||||
#: motions/views.py:256
|
|
||||||
msgid "Motion updated"
|
|
||||||
msgstr "Moção actualizada"
|
|
||||||
|
|
||||||
#: motions/views.py:260
|
|
||||||
msgid "All supporters removed"
|
|
||||||
msgstr "Todos os apoiantes removidos"
|
|
||||||
|
|
||||||
#: motions/views.py:264
|
|
||||||
msgid "Comment {} updated"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:298 motions/views.py:310
|
|
||||||
msgid "Version"
|
|
||||||
msgstr "Versão"
|
|
||||||
|
|
||||||
#: motions/views.py:302
|
|
||||||
#, python-format
|
|
||||||
msgid "Version %d permitted successfully."
|
|
||||||
msgstr "Versão %d permitida com sucesso."
|
|
||||||
|
|
||||||
#: motions/views.py:307
|
|
||||||
msgid "You can not delete the active version of a motion."
|
|
||||||
msgstr "Não podes eliminar a versão activa de uma moção.."
|
|
||||||
|
|
||||||
#: motions/views.py:312
|
|
||||||
msgid "deleted"
|
|
||||||
msgstr "eliminada"
|
|
||||||
|
|
||||||
#: motions/views.py:314
|
|
||||||
#, python-format
|
|
||||||
msgid "Version %d deleted successfully."
|
|
||||||
msgstr "Versão %d eliminada com sucesso."
|
|
||||||
|
|
||||||
#: motions/views.py:337
|
|
||||||
msgid "You can not support this motion."
|
|
||||||
msgstr "Não podes apoiar esta moção."
|
|
||||||
|
|
||||||
#: motions/views.py:339
|
|
||||||
msgid "Motion supported"
|
|
||||||
msgstr "Moção apoiada"
|
|
||||||
|
|
||||||
#: motions/views.py:343
|
|
||||||
msgid "You have supported this motion successfully."
|
|
||||||
msgstr "Apoiaste esta moção com sucesso."
|
|
||||||
|
|
||||||
#: motions/views.py:348
|
|
||||||
msgid "You can not unsupport this motion."
|
|
||||||
msgstr "Não podes desapoiar esta moção."
|
|
||||||
|
|
||||||
#: motions/views.py:350
|
|
||||||
msgid "Motion unsupported"
|
|
||||||
msgstr "Moção não apoiada"
|
|
||||||
|
|
||||||
#: motions/views.py:351
|
|
||||||
msgid "You have unsupported this motion successfully."
|
|
||||||
msgstr "Desapoiaste esta moção com sucesso."
|
|
||||||
|
|
||||||
#: motions/views.py:374
|
|
||||||
msgid "Invalid data. State must be an integer."
|
|
||||||
msgstr "Dados inválidos. O estado deve ser um inteiro."
|
|
||||||
|
|
||||||
#: motions/views.py:377
|
|
||||||
#, python-format
|
|
||||||
msgid "You can not set the state to %(state_id)d."
|
|
||||||
msgstr "Não podes definir o estado para %(state_id)d."
|
|
||||||
|
|
||||||
#: motions/views.py:385
|
|
||||||
#, python-format
|
|
||||||
msgid "The state of the motion was set to %s."
|
|
||||||
msgstr "O estado da moção foi definido para %s."
|
|
||||||
|
|
||||||
#: motions/views.py:389 motions/views.py:458 motions/views.py:726
|
|
||||||
msgid "State set to"
|
|
||||||
msgstr "Estado definido para"
|
|
||||||
|
|
||||||
#: motions/views.py:413
|
|
||||||
msgid "Invalid data. Recommendation must be an integer."
|
|
||||||
msgstr "Dados inválidos. A recomendação deve ser um inteiro."
|
|
||||||
|
|
||||||
#: motions/views.py:417
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "You can not set the recommendation to {recommendation_state_id}."
|
|
||||||
msgstr "Não podes definir a recomendação para {recommendation_state_id}."
|
|
||||||
|
|
||||||
#: motions/views.py:427
|
|
||||||
#, python-format
|
|
||||||
msgid "The recommendation of the motion was set to %s."
|
|
||||||
msgstr "A recomendação da moção foi definida para %s."
|
|
||||||
|
|
||||||
#: motions/views.py:431
|
|
||||||
msgid "Recommendation set to"
|
|
||||||
msgstr "Recomendação definida para"
|
|
||||||
|
|
||||||
#: motions/views.py:439
|
|
||||||
msgid "Cannot set an empty recommendation."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:479
|
|
||||||
msgid "Vote created"
|
|
||||||
msgstr "Voto criado"
|
|
||||||
|
|
||||||
#: motions/views.py:483
|
|
||||||
msgid "Vote created successfully."
|
|
||||||
msgstr "Voto criado com sucesso."
|
|
||||||
|
|
||||||
#: motions/views.py:509
|
|
||||||
msgid "Vote updated"
|
|
||||||
msgstr "Voto actualizado"
|
|
||||||
|
|
||||||
#: motions/views.py:518
|
|
||||||
msgid "Vote deleted"
|
|
||||||
msgstr "Voto excluído"
|
|
||||||
|
|
||||||
#: motions/views.py:652
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"Numbering aborted because the motion identifier \"%s\" already exists "
|
|
||||||
"outside of this category."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:675
|
|
||||||
msgid ""
|
|
||||||
"Error: At least one identifier of this category does already exist in "
|
|
||||||
"another category."
|
|
||||||
msgstr "Erro: Pelo menos um identificador desta categoria já existe noutra categoria."
|
|
||||||
|
|
||||||
#: motions/views.py:680
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "All motions in category {category} numbered successfully."
|
|
||||||
msgstr "Todas as moções na categoria {category} numeradas com sucesso."
|
|
||||||
|
|
||||||
#: motions/views.py:731
|
|
||||||
msgid "Followed recommendations successfully."
|
|
||||||
msgstr "Recomendações seguidas com sucesso."
|
|
||||||
|
|
||||||
#: poll/models.py:194
|
|
||||||
msgid "majority"
|
|
||||||
msgstr "maioria"
|
|
||||||
|
|
||||||
#: poll/models.py:196 poll/models.py:198
|
|
||||||
msgid "undocumented"
|
|
||||||
msgstr "indocumentado"
|
|
||||||
|
|
||||||
#: poll/serializers.py:16
|
|
||||||
msgid "Value for {} must not be less than -2"
|
|
||||||
msgstr "Valor para {} não pode ser inferior a -2"
|
|
||||||
|
|
||||||
#: users/serializers.py:49
|
|
||||||
msgid ""
|
|
||||||
"The groups this user belongs to. A user will get all permissions granted to "
|
|
||||||
"each of his/her groups."
|
|
||||||
msgstr "Os grupos a que este utilizador pertence. Um utilizador terá todas as permissões concedidas para cada um dos seus grupos."
|
|
||||||
|
|
||||||
#: users/serializers.py:72
|
|
||||||
msgid "Username, given name and surname can not all be empty."
|
|
||||||
msgstr "Username, primeiro nome e apelido não podem estar todos vazios."
|
|
||||||
|
|
||||||
#: users/serializers.py:109
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "Incorrect value \"{value}\". Expected app_label.codename string."
|
|
||||||
msgstr "Valor incorrecto \"{value}\". Esperava-se uma string app_label.codename."
|
|
||||||
|
|
||||||
#: users/serializers.py:110
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "Invalid permission \"{value}\". Object does not exist."
|
|
||||||
msgstr "Permissão inválida \"{value}\". O objecto não existe."
|
|
||||||
|
|
||||||
#: users/views.py:91
|
|
||||||
msgid "You can not deactivate yourself."
|
|
||||||
msgstr "Não podes desactivar-te a ti mesmo."
|
|
||||||
|
|
||||||
#: users/views.py:114
|
|
||||||
msgid "You can not delete yourself."
|
|
||||||
msgstr "Não podes apagar-te a ti mesmo."
|
|
||||||
|
|
||||||
#: users/views.py:131
|
|
||||||
msgid "Password successfully reset."
|
|
||||||
msgstr "Senha redefinida com sucesso."
|
|
||||||
|
|
||||||
#: users/views.py:172
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{number} users successfully imported."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: users/views.py:410
|
|
||||||
msgid "Cookies have to be enabled to use OpenSlides."
|
|
||||||
msgstr "Os cookies têm de estar activados para usar o OpenSlides."
|
|
||||||
|
|
||||||
#: users/views.py:413
|
|
||||||
msgid "Username or password is not correct."
|
|
||||||
msgstr "Username ou senha incorrectos."
|
|
||||||
|
|
||||||
#: users/views.py:439
|
|
||||||
#, python-brace-format
|
|
||||||
msgid ""
|
|
||||||
"Installation was successfully. Use {username} and {password} for first "
|
|
||||||
"login. Important: Please change your password!"
|
|
||||||
msgstr "Instalação com sucesso. Usa {username} e {password} no primeiro login. Importante: Por favor altera a tua senha!"
|
|
||||||
|
|
||||||
#: users/views.py:462
|
|
||||||
msgid "You are not authenticated."
|
|
||||||
msgstr "Não estás autenticado."
|
|
||||||
|
|
||||||
#: users/views.py:509
|
|
||||||
msgid "Old password does not match."
|
|
||||||
msgstr "A senha antiga não corresponde."
|
|
Binary file not shown.
@ -1,672 +0,0 @@
|
|||||||
# Language file of OpenSlides used by Transifex:
|
|
||||||
# https://www.transifex.com/openslides/openslides/
|
|
||||||
# Copyright (C) 2011–2015 by OpenSlides team, see AUTHORS.
|
|
||||||
# This file is distributed under the same license as the OpenSlides package.
|
|
||||||
# Translators:
|
|
||||||
# Andreas Engler <engel.a@web.de>, 2017-2018
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: OpenSlides\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2018-05-23 16:13+0200\n"
|
|
||||||
"PO-Revision-Date: 2018-05-23 14:15+0000\n"
|
|
||||||
"Last-Translator: Emanuel Schütze <emanuel.schuetze@intevation.de>\n"
|
|
||||||
"Language-Team: Russian (http://www.transifex.com/openslides/openslides/language/ru/)\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Language: ru\n"
|
|
||||||
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
|
|
||||||
|
|
||||||
#: agenda/models.py:206
|
|
||||||
msgid "Agenda item"
|
|
||||||
msgstr "Пункт плана"
|
|
||||||
|
|
||||||
#: agenda/models.py:207
|
|
||||||
msgid "Hidden item"
|
|
||||||
msgstr "Скрытый элемент"
|
|
||||||
|
|
||||||
#: agenda/models.py:356
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{user} is already on the list of speakers."
|
|
||||||
msgstr "{user} уже в списке спикеров."
|
|
||||||
|
|
||||||
#: agenda/models.py:359
|
|
||||||
msgid "An anonymous user can not be on lists of speakers."
|
|
||||||
msgstr "Анонимный пользователь не может быть в списке спикеров."
|
|
||||||
|
|
||||||
#: agenda/views.py:116
|
|
||||||
msgid "The list of speakers is closed."
|
|
||||||
msgstr "Список спикеров закрыт."
|
|
||||||
|
|
||||||
#: agenda/views.py:125 agenda/views.py:150
|
|
||||||
msgid "User does not exist."
|
|
||||||
msgstr "Пользователь не существует."
|
|
||||||
|
|
||||||
#: agenda/views.py:133
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully added to the list of speakers."
|
|
||||||
msgstr "Пользователь %s был успешно добавлен в список спикеров."
|
|
||||||
|
|
||||||
#: agenda/views.py:154
|
|
||||||
msgid "Marked has to be a bool."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:163
|
|
||||||
msgid "The user is not in the list of speakers."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:168
|
|
||||||
msgid "You are successfully marked the speaker."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:170
|
|
||||||
msgid "You are successfully unmarked the speaker."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:187
|
|
||||||
msgid "You are not on the list of speakers."
|
|
||||||
msgstr "Вас нет в списке спикеров."
|
|
||||||
|
|
||||||
#: agenda/views.py:190
|
|
||||||
msgid "You are successfully removed from the list of speakers."
|
|
||||||
msgstr "Вы успешно удалены из списка спикеров."
|
|
||||||
|
|
||||||
#: agenda/views.py:212
|
|
||||||
msgid "speakers have been removed from the list of speakers."
|
|
||||||
msgstr "Спикеры удалены из списка спикеров."
|
|
||||||
|
|
||||||
#: agenda/views.py:214
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s has been removed from the list of speakers."
|
|
||||||
msgstr "Пользователь %s удален из списка спикеров."
|
|
||||||
|
|
||||||
#: agenda/views.py:216
|
|
||||||
msgid "No speakers have been removed from the list of speakers."
|
|
||||||
msgstr "Никакие спикеры не были удалены из списка спикеров."
|
|
||||||
|
|
||||||
#: agenda/views.py:236
|
|
||||||
msgid "The list of speakers is empty."
|
|
||||||
msgstr "Список спикеров пуст."
|
|
||||||
|
|
||||||
#: agenda/views.py:241
|
|
||||||
msgid "Speaker does not exist."
|
|
||||||
msgstr "Спикер не существует."
|
|
||||||
|
|
||||||
#: agenda/views.py:243
|
|
||||||
msgid "User is now speaking."
|
|
||||||
msgstr "Пользователь сейчас говорит."
|
|
||||||
|
|
||||||
#: agenda/views.py:254
|
|
||||||
#, python-format
|
|
||||||
msgid "There is no one speaking at the moment according to %(item)s."
|
|
||||||
msgstr "В данный момент нет спикера, согласованного с %(item)s."
|
|
||||||
|
|
||||||
#: agenda/views.py:256
|
|
||||||
msgid "The speech is finished now."
|
|
||||||
msgstr "Речь закончена."
|
|
||||||
|
|
||||||
#: agenda/views.py:275 agenda/views.py:287 assignments/views.py:222
|
|
||||||
msgid "Invalid data."
|
|
||||||
msgstr "Неверные данные."
|
|
||||||
|
|
||||||
#: agenda/views.py:300
|
|
||||||
msgid "List of speakers successfully sorted."
|
|
||||||
msgstr "Список ораторов успешно отсортирован."
|
|
||||||
|
|
||||||
#: agenda/views.py:309
|
|
||||||
msgid "Numbering of agenda items is deactivated."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: agenda/views.py:312
|
|
||||||
msgid "The agenda has been numbered."
|
|
||||||
msgstr "План был пронумерован."
|
|
||||||
|
|
||||||
#: agenda/views.py:337
|
|
||||||
msgid "There must not be a hierarchical loop. Please reload the page."
|
|
||||||
msgstr "Там не должно быть иерархического цикла. Перезагрузите пожалуйста страницу."
|
|
||||||
|
|
||||||
#: agenda/views.py:341
|
|
||||||
msgid "The agenda has been sorted."
|
|
||||||
msgstr "Повестка дня отсортирована."
|
|
||||||
|
|
||||||
#: assignments/models.py:164
|
|
||||||
msgid "Election"
|
|
||||||
msgstr "Выборы"
|
|
||||||
|
|
||||||
#: assignments/serializers.py:31
|
|
||||||
msgid "Value for {} must be greater than 0"
|
|
||||||
msgstr "Значение {} должно быть больше 0"
|
|
||||||
|
|
||||||
#: assignments/serializers.py:149
|
|
||||||
#, python-format
|
|
||||||
msgid "You have to submit data for %d candidates."
|
|
||||||
msgstr "Вы должны предоставить данные для %d кандидатов."
|
|
||||||
|
|
||||||
#: assignments/serializers.py:153 motions/serializers.py:236
|
|
||||||
#, python-format
|
|
||||||
msgid "You have to submit data for %d vote values."
|
|
||||||
msgstr "Вы должны представить данные для %d значения голосования."
|
|
||||||
|
|
||||||
#: assignments/serializers.py:157 motions/serializers.py:240
|
|
||||||
#, python-format
|
|
||||||
msgid "Vote value %s is invalid."
|
|
||||||
msgstr " Количество голосов %s является недопустимым."
|
|
||||||
|
|
||||||
#: assignments/views.py:66
|
|
||||||
msgid "You are already elected."
|
|
||||||
msgstr "Вы уже избраны."
|
|
||||||
|
|
||||||
#: assignments/views.py:76
|
|
||||||
msgid "You can not candidate to this election because it is finished."
|
|
||||||
msgstr "Вы не можете быть кандидатом на этих выборах, потому что они уже закончены."
|
|
||||||
|
|
||||||
#: assignments/views.py:85
|
|
||||||
msgid "You were nominated successfully."
|
|
||||||
msgstr "Вы были успешно выдвинуты."
|
|
||||||
|
|
||||||
#: assignments/views.py:90
|
|
||||||
msgid ""
|
|
||||||
"You can not withdraw your candidature to this election because it is "
|
|
||||||
"finished."
|
|
||||||
msgstr "Вы не можете снять свою кандидатуру на этих выборах, потому что они уже закончены."
|
|
||||||
|
|
||||||
#: assignments/views.py:95
|
|
||||||
msgid "You are not a candidate of this election."
|
|
||||||
msgstr "Вы не являетесь кандидатом этих выборов."
|
|
||||||
|
|
||||||
#: assignments/views.py:97
|
|
||||||
msgid "You have withdrawn your candidature successfully."
|
|
||||||
msgstr "Вы успешно отозвали свою кандидатуру."
|
|
||||||
|
|
||||||
#: assignments/views.py:106
|
|
||||||
#, python-format
|
|
||||||
msgid "Invalid data. Expected dictionary, got %s."
|
|
||||||
msgstr "Неверные данные. Ожидаемый словарь, получил %s."
|
|
||||||
|
|
||||||
#: assignments/views.py:112
|
|
||||||
msgid "Invalid data. Expected something like {\"user\": <id>}."
|
|
||||||
msgstr "Неверные данные. Ожидаемое что-то вроде {\"user\": <id>}."
|
|
||||||
|
|
||||||
#: assignments/views.py:116
|
|
||||||
#, python-format
|
|
||||||
msgid "Invalid data. User %d does not exist."
|
|
||||||
msgstr "Неверные данные. Пользователь %d не существует."
|
|
||||||
|
|
||||||
#: assignments/views.py:136
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is already elected."
|
|
||||||
msgstr "Пользователь %s уже избран."
|
|
||||||
|
|
||||||
#: assignments/views.py:138
|
|
||||||
msgid "You can not nominate someone to this election because it is finished."
|
|
||||||
msgstr "Вы не можете выдвинуть кого-то на эти выборы, потому что они уже закончены."
|
|
||||||
|
|
||||||
#: assignments/views.py:144
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is already nominated."
|
|
||||||
msgstr "Пользователь %s уже выдвинут."
|
|
||||||
|
|
||||||
#: assignments/views.py:149
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was nominated successfully."
|
|
||||||
msgstr "Пользователь %s был успешно выдвинут."
|
|
||||||
|
|
||||||
#: assignments/views.py:156
|
|
||||||
msgid ""
|
|
||||||
"You can not delete someone's candidature to this election because it is "
|
|
||||||
"finished."
|
|
||||||
msgstr "Вы не можете удалять чью-то кандидатуру на этих выборах, потому что они уже закончены."
|
|
||||||
|
|
||||||
#: assignments/views.py:159
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s has no status in this election."
|
|
||||||
msgstr "Пользователь %s не имеет статуса в этих выборах."
|
|
||||||
|
|
||||||
#: assignments/views.py:161
|
|
||||||
#, python-format
|
|
||||||
msgid "Candidate %s was withdrawn successfully."
|
|
||||||
msgstr "Кандидат %s был успешно снят."
|
|
||||||
|
|
||||||
#: assignments/views.py:173
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is not a candidate of this election."
|
|
||||||
msgstr "Пользователь %s не является кандидатом на этих выборах."
|
|
||||||
|
|
||||||
#: assignments/views.py:175
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully elected."
|
|
||||||
msgstr "Пользователь %s был успешно избран."
|
|
||||||
|
|
||||||
#: assignments/views.py:179
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s is not an elected candidate of this election."
|
|
||||||
msgstr "Пользователь %s не был избран на этих выборах."
|
|
||||||
|
|
||||||
#: assignments/views.py:182
|
|
||||||
#, python-format
|
|
||||||
msgid "User %s was successfully unelected."
|
|
||||||
msgstr "Пользователь %s не был успешно избран."
|
|
||||||
|
|
||||||
#: assignments/views.py:192
|
|
||||||
msgid "Can not create ballot because there are no candidates."
|
|
||||||
msgstr "Невозможно создать избирательный бюллетень, потому что нет кандидатов."
|
|
||||||
|
|
||||||
#: assignments/views.py:195
|
|
||||||
msgid "Ballot created successfully."
|
|
||||||
msgstr "Избирательный бюллетень успешно создан."
|
|
||||||
|
|
||||||
#: assignments/views.py:210
|
|
||||||
msgid "users has to be a list of IDs."
|
|
||||||
msgstr "Пользователям должен быть список идентификаторов."
|
|
||||||
|
|
||||||
#: assignments/views.py:237
|
|
||||||
msgid "Assignment related users successfully sorted."
|
|
||||||
msgstr "Связанные присваивания пользователям успешно отсортированы."
|
|
||||||
|
|
||||||
#: core/config.py:50 core/config.py:76
|
|
||||||
msgid "The config variable {} was not found."
|
|
||||||
msgstr "Переменная конфигурации {} не была найдена."
|
|
||||||
|
|
||||||
#: core/config.py:85
|
|
||||||
#, python-format
|
|
||||||
msgid "Wrong datatype. Expected %(expected_type)s, got %(got_type)s."
|
|
||||||
msgstr "Неправильный тип данных. Ожидаемое %(expected_type)s, получили %(got_type)s."
|
|
||||||
|
|
||||||
#: core/config.py:95
|
|
||||||
msgid "Invalid input. Choice does not match."
|
|
||||||
msgstr "Неправильный ввод. Выбор не соответствует."
|
|
||||||
|
|
||||||
#: core/config.py:105
|
|
||||||
msgid "motions_comments has to be a dict."
|
|
||||||
msgstr "motions_comments должен быть dict."
|
|
||||||
|
|
||||||
#: core/config.py:111
|
|
||||||
msgid "Each id has to be an int."
|
|
||||||
msgstr "Каждый идентификатор должен быть int."
|
|
||||||
|
|
||||||
#: core/config.py:114
|
|
||||||
msgid "Each id has to be greater then 0."
|
|
||||||
msgstr "Каждый идентификатор должен быть больше 0."
|
|
||||||
|
|
||||||
#: core/config.py:118
|
|
||||||
msgid "Each commentsfield in motions_comments has to be a dict."
|
|
||||||
msgstr "Каждое поле комментариев в motions_comments должно быть dict."
|
|
||||||
|
|
||||||
#: core/config.py:120
|
|
||||||
msgid "A name and a public property have to be given."
|
|
||||||
msgstr "Имя и публичное свойство должны быть заполнены."
|
|
||||||
|
|
||||||
#: core/config.py:122
|
|
||||||
msgid "name has to be string."
|
|
||||||
msgstr "имя должно быть строкой."
|
|
||||||
|
|
||||||
#: core/config.py:124
|
|
||||||
msgid "public property has to be bool."
|
|
||||||
msgstr "Публичное свойство должна быть BOOL."
|
|
||||||
|
|
||||||
#: core/config.py:130
|
|
||||||
msgid "This has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/config.py:137 core/config.py:153
|
|
||||||
msgid "{} has to be given."
|
|
||||||
msgstr "{} должно быть дано."
|
|
||||||
|
|
||||||
#: core/config.py:139 core/config.py:155
|
|
||||||
msgid "{} has to be a string."
|
|
||||||
msgstr "{} должна быть строкой."
|
|
||||||
|
|
||||||
#: core/config.py:143
|
|
||||||
msgid "Translations has to be a list."
|
|
||||||
msgstr "Переводы должны быть списком."
|
|
||||||
|
|
||||||
#: core/config.py:146
|
|
||||||
msgid "Every value has to be a dict, not {}."
|
|
||||||
msgstr "Каждое значение должно быть dict, а не {}."
|
|
||||||
|
|
||||||
#: core/config.py:177
|
|
||||||
msgid "Too many values for config variables {} found."
|
|
||||||
msgstr "Найдено слишком много значений для переменных конфигурации {}."
|
|
||||||
|
|
||||||
#: core/config.py:261
|
|
||||||
msgid "Invalid value for config attribute input_type."
|
|
||||||
msgstr "Недопустимое значение атрибута конфигурации input_type."
|
|
||||||
|
|
||||||
#: core/config.py:263
|
|
||||||
msgid ""
|
|
||||||
"Either config attribute 'choices' must not be None or 'input_type' must not "
|
|
||||||
"be 'choice'."
|
|
||||||
msgstr "Либо конфигурационный атрибут 'choices' не должен быть None или 'input_type' не должно быть 'choice'."
|
|
||||||
|
|
||||||
#: core/config.py:266
|
|
||||||
msgid ""
|
|
||||||
"Either config attribute 'choices' must be None or 'input_type' must be "
|
|
||||||
"'choice'."
|
|
||||||
msgstr "Либо конфигурационный атрибут 'choices' должен быть None или 'input_type' должно быть 'choice'."
|
|
||||||
|
|
||||||
#: core/config.py:276
|
|
||||||
msgid "General"
|
|
||||||
msgstr "Генеральный"
|
|
||||||
|
|
||||||
#: core/views.py:277
|
|
||||||
msgid "The data has to be a list."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:280
|
|
||||||
msgid "All elements have to be dicts."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:420
|
|
||||||
msgid "The data has to be a dict."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:426
|
|
||||||
msgid "The id \"{}\" has to be int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:432
|
|
||||||
msgid "Prune has to be an object."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:435
|
|
||||||
msgid "The prune projector id has to be int."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:440
|
|
||||||
msgid "The projector with id \"{}\" does not exist"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:444
|
|
||||||
msgid "Prune element has to be a dict or not given."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: core/views.py:772
|
|
||||||
msgid "All chat messages deleted successfully."
|
|
||||||
msgstr "Все сообщения чата успешно удалены."
|
|
||||||
|
|
||||||
#: mediafiles/models.py:87
|
|
||||||
msgid "unknown"
|
|
||||||
msgstr "неизвестный"
|
|
||||||
|
|
||||||
#: motions/models.py:190
|
|
||||||
msgid "Motion"
|
|
||||||
msgstr "Заявление"
|
|
||||||
|
|
||||||
#: motions/models.py:744
|
|
||||||
msgid "new"
|
|
||||||
msgstr "Новый"
|
|
||||||
|
|
||||||
#: motions/models.py:969
|
|
||||||
#, python-format
|
|
||||||
msgid "%(time_and_messages)s by %(person)s"
|
|
||||||
msgstr "%(time_and_messages)s от %(person)s"
|
|
||||||
|
|
||||||
#: motions/serializers.py:36
|
|
||||||
#, python-format
|
|
||||||
msgid "Workflow %(pk)d does not exist."
|
|
||||||
msgstr "Процесс %(pk)d не существует."
|
|
||||||
|
|
||||||
#: motions/signals.py:22
|
|
||||||
msgid "submitted"
|
|
||||||
msgstr "Отправлено"
|
|
||||||
|
|
||||||
#: motions/signals.py:27 motions/signals.py:60
|
|
||||||
msgid "accepted"
|
|
||||||
msgstr "принято"
|
|
||||||
|
|
||||||
#: motions/signals.py:32 motions/signals.py:66
|
|
||||||
msgid "rejected"
|
|
||||||
msgstr "отвергнуто"
|
|
||||||
|
|
||||||
#: motions/signals.py:37
|
|
||||||
msgid "not decided"
|
|
||||||
msgstr "не решено"
|
|
||||||
|
|
||||||
#: motions/signals.py:47
|
|
||||||
msgid "published"
|
|
||||||
msgstr "опубликовано"
|
|
||||||
|
|
||||||
#: motions/signals.py:52 motions/views.py:300
|
|
||||||
msgid "permitted"
|
|
||||||
msgstr "разрешено"
|
|
||||||
|
|
||||||
#: motions/signals.py:72
|
|
||||||
msgid "withdrawed"
|
|
||||||
msgstr "отозваны"
|
|
||||||
|
|
||||||
#: motions/signals.py:77
|
|
||||||
msgid "adjourned"
|
|
||||||
msgstr "отложено"
|
|
||||||
|
|
||||||
#: motions/signals.py:83
|
|
||||||
msgid "not concerned"
|
|
||||||
msgstr "не касается"
|
|
||||||
|
|
||||||
#: motions/signals.py:89
|
|
||||||
msgid "refered to committee"
|
|
||||||
msgstr "отнесено к комитету"
|
|
||||||
|
|
||||||
#: motions/signals.py:95
|
|
||||||
msgid "needs review"
|
|
||||||
msgstr "требует пересмотра"
|
|
||||||
|
|
||||||
#: motions/signals.py:100
|
|
||||||
msgid "rejected (not authorized)"
|
|
||||||
msgstr "отклонено (не авторизован)"
|
|
||||||
|
|
||||||
#: motions/views.py:110
|
|
||||||
msgid "The parent motion does not exist."
|
|
||||||
msgstr "Родительское предложение не существует."
|
|
||||||
|
|
||||||
#: motions/views.py:154
|
|
||||||
msgid "Motion created"
|
|
||||||
msgstr "Заявление создано"
|
|
||||||
|
|
||||||
#: motions/views.py:256
|
|
||||||
msgid "Motion updated"
|
|
||||||
msgstr "Заявление обновлено"
|
|
||||||
|
|
||||||
#: motions/views.py:260
|
|
||||||
msgid "All supporters removed"
|
|
||||||
msgstr "Все сторонники удалены"
|
|
||||||
|
|
||||||
#: motions/views.py:264
|
|
||||||
msgid "Comment {} updated"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:298 motions/views.py:310
|
|
||||||
msgid "Version"
|
|
||||||
msgstr "Версия"
|
|
||||||
|
|
||||||
#: motions/views.py:302
|
|
||||||
#, python-format
|
|
||||||
msgid "Version %d permitted successfully."
|
|
||||||
msgstr "Версия %d успешно стартовала."
|
|
||||||
|
|
||||||
#: motions/views.py:307
|
|
||||||
msgid "You can not delete the active version of a motion."
|
|
||||||
msgstr "Вы не можете удалить активную версию заявления."
|
|
||||||
|
|
||||||
#: motions/views.py:312
|
|
||||||
msgid "deleted"
|
|
||||||
msgstr "удалено "
|
|
||||||
|
|
||||||
#: motions/views.py:314
|
|
||||||
#, python-format
|
|
||||||
msgid "Version %d deleted successfully."
|
|
||||||
msgstr "Версия %d успешно удалена."
|
|
||||||
|
|
||||||
#: motions/views.py:337
|
|
||||||
msgid "You can not support this motion."
|
|
||||||
msgstr "Вы не можете поддерживать это заявление."
|
|
||||||
|
|
||||||
#: motions/views.py:339
|
|
||||||
msgid "Motion supported"
|
|
||||||
msgstr "Заявление поддерживается"
|
|
||||||
|
|
||||||
#: motions/views.py:343
|
|
||||||
msgid "You have supported this motion successfully."
|
|
||||||
msgstr "Вы успешно поддержали это заявление."
|
|
||||||
|
|
||||||
#: motions/views.py:348
|
|
||||||
msgid "You can not unsupport this motion."
|
|
||||||
msgstr "Вы не можете поддерживать это заявление."
|
|
||||||
|
|
||||||
#: motions/views.py:350
|
|
||||||
msgid "Motion unsupported"
|
|
||||||
msgstr "Заявление без поддержки"
|
|
||||||
|
|
||||||
#: motions/views.py:351
|
|
||||||
msgid "You have unsupported this motion successfully."
|
|
||||||
msgstr "Вы не успешно поддерживаете это заявление."
|
|
||||||
|
|
||||||
#: motions/views.py:374
|
|
||||||
msgid "Invalid data. State must be an integer."
|
|
||||||
msgstr "Неверные данные. Состояние должно быть целым числом."
|
|
||||||
|
|
||||||
#: motions/views.py:377
|
|
||||||
#, python-format
|
|
||||||
msgid "You can not set the state to %(state_id)d."
|
|
||||||
msgstr "Вы не можете установить состояние на %(state_id)d."
|
|
||||||
|
|
||||||
#: motions/views.py:385
|
|
||||||
#, python-format
|
|
||||||
msgid "The state of the motion was set to %s."
|
|
||||||
msgstr "Состояние заявления было установлено в %s."
|
|
||||||
|
|
||||||
#: motions/views.py:389 motions/views.py:458 motions/views.py:726
|
|
||||||
msgid "State set to"
|
|
||||||
msgstr "Состояние установлено на"
|
|
||||||
|
|
||||||
#: motions/views.py:413
|
|
||||||
msgid "Invalid data. Recommendation must be an integer."
|
|
||||||
msgstr "Неверные данные. Рекомендация должна быть целом числом."
|
|
||||||
|
|
||||||
#: motions/views.py:417
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "You can not set the recommendation to {recommendation_state_id}."
|
|
||||||
msgstr "Вы не можете установить рекомендацию {recommendation_state_id}."
|
|
||||||
|
|
||||||
#: motions/views.py:427
|
|
||||||
#, python-format
|
|
||||||
msgid "The recommendation of the motion was set to %s."
|
|
||||||
msgstr "Рекомендация заявления была установлена на %s."
|
|
||||||
|
|
||||||
#: motions/views.py:431
|
|
||||||
msgid "Recommendation set to"
|
|
||||||
msgstr "Рекомендацию установить на"
|
|
||||||
|
|
||||||
#: motions/views.py:439
|
|
||||||
msgid "Cannot set an empty recommendation."
|
|
||||||
msgstr "Невозможно установить пустую рекомендацию."
|
|
||||||
|
|
||||||
#: motions/views.py:479
|
|
||||||
msgid "Vote created"
|
|
||||||
msgstr "Голосование создано"
|
|
||||||
|
|
||||||
#: motions/views.py:483
|
|
||||||
msgid "Vote created successfully."
|
|
||||||
msgstr "Голосование успешно создано."
|
|
||||||
|
|
||||||
#: motions/views.py:509
|
|
||||||
msgid "Vote updated"
|
|
||||||
msgstr "Голосование обновлено"
|
|
||||||
|
|
||||||
#: motions/views.py:518
|
|
||||||
msgid "Vote deleted"
|
|
||||||
msgstr "Голосование удалено"
|
|
||||||
|
|
||||||
#: motions/views.py:652
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"Numbering aborted because the motion identifier \"%s\" already exists "
|
|
||||||
"outside of this category."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: motions/views.py:675
|
|
||||||
msgid ""
|
|
||||||
"Error: At least one identifier of this category does already exist in "
|
|
||||||
"another category."
|
|
||||||
msgstr "Ошибка: По крайней мере один идентификатор этой категории уже существует в другой категории."
|
|
||||||
|
|
||||||
#: motions/views.py:680
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "All motions in category {category} numbered successfully."
|
|
||||||
msgstr "Все заявления в категории {category} успешно пронумерованы."
|
|
||||||
|
|
||||||
#: motions/views.py:731
|
|
||||||
msgid "Followed recommendations successfully."
|
|
||||||
msgstr "Следующие рекомендации успешно."
|
|
||||||
|
|
||||||
#: poll/models.py:194
|
|
||||||
msgid "majority"
|
|
||||||
msgstr "большинство"
|
|
||||||
|
|
||||||
#: poll/models.py:196 poll/models.py:198
|
|
||||||
msgid "undocumented"
|
|
||||||
msgstr "недокументированный"
|
|
||||||
|
|
||||||
#: poll/serializers.py:16
|
|
||||||
msgid "Value for {} must not be less than -2"
|
|
||||||
msgstr "Значение для {} не должно быть меньше, чем -2"
|
|
||||||
|
|
||||||
#: users/serializers.py:49
|
|
||||||
msgid ""
|
|
||||||
"The groups this user belongs to. A user will get all permissions granted to "
|
|
||||||
"each of his/her groups."
|
|
||||||
msgstr "Группы, к которым принадлежит данный пользователь. Пользователь получит все права, предоставленные каждому из его / ее группы."
|
|
||||||
|
|
||||||
#: users/serializers.py:72
|
|
||||||
msgid "Username, given name and surname can not all be empty."
|
|
||||||
msgstr "Имя пользователя, имя и фамилия не могут быть пустыми."
|
|
||||||
|
|
||||||
#: users/serializers.py:109
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "Incorrect value \"{value}\". Expected app_label.codename string."
|
|
||||||
msgstr "Неверное значение \"{value}\". Ожидаемая app_label.codename строка."
|
|
||||||
|
|
||||||
#: users/serializers.py:110
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "Invalid permission \"{value}\". Object does not exist."
|
|
||||||
msgstr "Неверное разрешение \"{value}\". Объект не существует."
|
|
||||||
|
|
||||||
#: users/views.py:91
|
|
||||||
msgid "You can not deactivate yourself."
|
|
||||||
msgstr "Вы не можете отключить себя."
|
|
||||||
|
|
||||||
#: users/views.py:114
|
|
||||||
msgid "You can not delete yourself."
|
|
||||||
msgstr "Вы не можете удалить себя."
|
|
||||||
|
|
||||||
#: users/views.py:131
|
|
||||||
msgid "Password successfully reset."
|
|
||||||
msgstr "Пароль успешно сброшен."
|
|
||||||
|
|
||||||
#: users/views.py:172
|
|
||||||
#, python-brace-format
|
|
||||||
msgid "{number} users successfully imported."
|
|
||||||
msgstr "{number} пользователей успешно импортировано."
|
|
||||||
|
|
||||||
#: users/views.py:410
|
|
||||||
msgid "Cookies have to be enabled to use OpenSlides."
|
|
||||||
msgstr "Куки должны быть включены для пользования OpenSlides."
|
|
||||||
|
|
||||||
#: users/views.py:413
|
|
||||||
msgid "Username or password is not correct."
|
|
||||||
msgstr "Имя пользователя или пароль не является правильным."
|
|
||||||
|
|
||||||
#: users/views.py:439
|
|
||||||
#, python-brace-format
|
|
||||||
msgid ""
|
|
||||||
"Installation was successfully. Use {username} and {password} for first "
|
|
||||||
"login. Important: Please change your password!"
|
|
||||||
msgstr "Установка была успешна. Используйте {username} и {password} для первого входа в систему. Важно: Пожалуйста, измените пароль!"
|
|
||||||
|
|
||||||
#: users/views.py:462
|
|
||||||
msgid "You are not authenticated."
|
|
||||||
msgstr "Вы не авторизованы."
|
|
||||||
|
|
||||||
#: users/views.py:509
|
|
||||||
msgid "Old password does not match."
|
|
||||||
msgstr "Старый пароль не совпадает."
|
|
@ -1,6 +1,5 @@
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
|
|
||||||
from ..core.config import config
|
from ..core.config import config
|
||||||
from ..utils.autoupdate import inform_changed_data
|
from ..utils.autoupdate import inform_changed_data
|
||||||
@ -74,7 +73,7 @@ class Mediafile(RESTModelMixin, models.Model):
|
|||||||
try:
|
try:
|
||||||
size = self.mediafile.size
|
size = self.mediafile.size
|
||||||
except OSError:
|
except OSError:
|
||||||
size_string = _("unknown")
|
size_string = "unknown"
|
||||||
else:
|
else:
|
||||||
if size < 1024:
|
if size < 1024:
|
||||||
size_string = "< 1 kB"
|
size_string = "< 1 kB"
|
||||||
|
@ -7,7 +7,6 @@ from django.core.exceptions import ImproperlyConfigured, ValidationError
|
|||||||
from django.db import IntegrityError, models, transaction
|
from django.db import IntegrityError, models, transaction
|
||||||
from django.db.models import Max
|
from django.db.models import Max
|
||||||
from django.utils import formats, timezone
|
from django.utils import formats, timezone
|
||||||
from django.utils.translation import ugettext as _, ugettext_noop
|
|
||||||
from jsonfield import JSONField
|
from jsonfield import JSONField
|
||||||
|
|
||||||
from openslides.agenda.models import Item
|
from openslides.agenda.models import Item
|
||||||
@ -259,7 +258,7 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
("can_manage", "Can manage motions"),
|
("can_manage", "Can manage motions"),
|
||||||
)
|
)
|
||||||
ordering = ("identifier",)
|
ordering = ("identifier",)
|
||||||
verbose_name = ugettext_noop("Motion")
|
verbose_name = "Motion"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""
|
"""
|
||||||
@ -330,22 +329,16 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
if self.is_amendment():
|
if self.is_amendment():
|
||||||
parent_identifier = self.parent.identifier or ""
|
parent_identifier = self.parent.identifier or ""
|
||||||
if without_blank:
|
if without_blank:
|
||||||
prefix = "%s%s" % (
|
prefix = f"{parent_identifier} {config['motions_amendments_prefix']} "
|
||||||
parent_identifier,
|
|
||||||
config["motions_amendments_prefix"],
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
prefix = "%s %s " % (
|
prefix = f"{parent_identifier} {config['motions_amendments_prefix']} "
|
||||||
parent_identifier,
|
|
||||||
config["motions_amendments_prefix"],
|
|
||||||
)
|
|
||||||
elif self.category is None or not self.category.prefix:
|
elif self.category is None or not self.category.prefix:
|
||||||
prefix = ""
|
prefix = ""
|
||||||
else:
|
else:
|
||||||
if without_blank:
|
if without_blank:
|
||||||
prefix = "%s" % self.category.prefix
|
prefix = self.category.prefix
|
||||||
else:
|
else:
|
||||||
prefix = "%s " % self.category.prefix
|
prefix = f"{self.category.prefix} "
|
||||||
self._identifier_prefix = prefix
|
self._identifier_prefix = prefix
|
||||||
|
|
||||||
# Use the already assigned identifier_number, if the motion has one.
|
# Use the already assigned identifier_number, if the motion has one.
|
||||||
@ -386,10 +379,10 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
"""
|
"""
|
||||||
if initial_increment:
|
if initial_increment:
|
||||||
number += 1
|
number += 1
|
||||||
identifier = "%s%s" % (prefix, self.extend_identifier_number(number))
|
identifier = f"{prefix}{self.extend_identifier_number(number)}"
|
||||||
while Motion.objects.filter(identifier=identifier).exists():
|
while Motion.objects.filter(identifier=identifier).exists():
|
||||||
number += 1
|
number += 1
|
||||||
identifier = "%s%s" % (prefix, self.extend_identifier_number(number))
|
identifier = f"{prefix}{self.extend_identifier_number(number)}"
|
||||||
return number, identifier
|
return number, identifier
|
||||||
|
|
||||||
def extend_identifier_number(self, number):
|
def extend_identifier_number(self, number):
|
||||||
@ -438,7 +431,7 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
return poll
|
return poll
|
||||||
else:
|
else:
|
||||||
raise WorkflowError(
|
raise WorkflowError(
|
||||||
"You can not create a poll in state %s." % self.state.name
|
f"You can not create a poll in state {self.state.name}."
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -454,7 +447,7 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
|
|
||||||
'state' can be the id of a state object or a state object.
|
'state' can be the id of a state object or a state object.
|
||||||
"""
|
"""
|
||||||
if type(state) is int:
|
if isinstance(state, int):
|
||||||
state = State.objects.get(pk=state)
|
state = State.objects.get(pk=state)
|
||||||
|
|
||||||
if not state.dont_set_identifier:
|
if not state.dont_set_identifier:
|
||||||
@ -472,7 +465,7 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
workflow from config.
|
workflow from config.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if type(workflow) is int:
|
if isinstance(workflow, int):
|
||||||
workflow = Workflow.objects.get(pk=workflow)
|
workflow = Workflow.objects.get(pk=workflow)
|
||||||
|
|
||||||
if workflow is not None:
|
if workflow is not None:
|
||||||
@ -492,7 +485,7 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
|
|
||||||
'recommendation' can be the id of a state object or a state object.
|
'recommendation' can be the id of a state object or a state object.
|
||||||
"""
|
"""
|
||||||
if type(recommendation) is int:
|
if isinstance(recommendation, int):
|
||||||
recommendation = State.objects.get(pk=recommendation)
|
recommendation = State.objects.get(pk=recommendation)
|
||||||
self.recommendation = recommendation
|
self.recommendation = recommendation
|
||||||
|
|
||||||
@ -517,7 +510,7 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
Note: It has to be the same return value like in JavaScript.
|
Note: It has to be the same return value like in JavaScript.
|
||||||
"""
|
"""
|
||||||
if self.identifier:
|
if self.identifier:
|
||||||
title = "%s %s" % (_(self._meta.verbose_name), self.identifier)
|
title = f"{self._meta.verbose_name} {self.identifier}"
|
||||||
else:
|
else:
|
||||||
title = self.title
|
title = self.title
|
||||||
return title
|
return title
|
||||||
@ -530,9 +523,9 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
Note: It has to be the same return value like in JavaScript.
|
Note: It has to be the same return value like in JavaScript.
|
||||||
"""
|
"""
|
||||||
if self.identifier:
|
if self.identifier:
|
||||||
title = "%s %s" % (_(self._meta.verbose_name), self.identifier)
|
title = f"{self._meta.verbose_name} {self.identifier}"
|
||||||
else:
|
else:
|
||||||
title = "%s (%s)" % (self.title, _(self._meta.verbose_name))
|
title = f"{self.title} ({self._meta.verbose_name})"
|
||||||
return title
|
return title
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -555,8 +548,7 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
"""
|
"""
|
||||||
Write a log message.
|
Write a log message.
|
||||||
|
|
||||||
The message should be in English and translatable,
|
The message should be in English.
|
||||||
e. g. motion.write_log(message_list=[ugettext_noop('Message Text')])
|
|
||||||
"""
|
"""
|
||||||
if person and not person.is_authenticated:
|
if person and not person.is_authenticated:
|
||||||
person = None
|
person = None
|
||||||
@ -679,9 +671,9 @@ class SubmitterManager(models.Manager):
|
|||||||
for the initial sorting of the submitters.
|
for the initial sorting of the submitters.
|
||||||
"""
|
"""
|
||||||
if self.filter(user=user, motion=motion).exists():
|
if self.filter(user=user, motion=motion).exists():
|
||||||
raise OpenSlidesError(_("{user} is already a submitter.").format(user=user))
|
raise OpenSlidesError(f"{user} is already a submitter.")
|
||||||
if isinstance(user, AnonymousUser):
|
if isinstance(user, AnonymousUser):
|
||||||
raise OpenSlidesError(_("An anonymous user can not be a submitter."))
|
raise OpenSlidesError("An anonymous user can not be a submitter.")
|
||||||
weight = (
|
weight = (
|
||||||
self.filter(motion=motion).aggregate(models.Max("weight"))["weight__max"]
|
self.filter(motion=motion).aggregate(models.Max("weight"))["weight__max"]
|
||||||
or 0
|
or 0
|
||||||
@ -804,8 +796,7 @@ class MotionChangeRecommendation(RESTModelMixin, models.Model):
|
|||||||
|
|
||||||
if self.collides_with_other_recommendation(recommendations):
|
if self.collides_with_other_recommendation(recommendations):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
"The recommendation collides with an existing one (line %s - %s)."
|
f"The recommendation collides with an existing one (line {self.line_from} - {self.line_to})."
|
||||||
% (self.line_from, self.line_to)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return super().save(*args, **kwargs)
|
return super().save(*args, **kwargs)
|
||||||
@ -815,11 +806,7 @@ class MotionChangeRecommendation(RESTModelMixin, models.Model):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""Return a string, representing this object."""
|
"""Return a string, representing this object."""
|
||||||
return "Recommendation for Motion %s, line %s - %s" % (
|
return f"Recommendation for Motion {self.motion_id}, line {self.line_from} - {self.line_to}"
|
||||||
self.motion_id,
|
|
||||||
self.line_from,
|
|
||||||
self.line_to,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Category(RESTModelMixin, models.Model):
|
class Category(RESTModelMixin, models.Model):
|
||||||
@ -875,7 +862,7 @@ class MotionBlock(RESTModelMixin, models.Model):
|
|||||||
agenda_items = GenericRelation(Item, related_name="topics")
|
agenda_items = GenericRelation(Item, related_name="topics")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = ugettext_noop("Motion block")
|
verbose_name = "Motion block"
|
||||||
default_permissions = ()
|
default_permissions = ()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@ -906,7 +893,7 @@ class MotionBlock(RESTModelMixin, models.Model):
|
|||||||
return self.title
|
return self.title
|
||||||
|
|
||||||
def get_agenda_title_with_type(self):
|
def get_agenda_title_with_type(self):
|
||||||
return "%s (%s)" % (self.get_agenda_title(), _(self._meta.verbose_name))
|
return f"{self.get_agenda_title()} ({self._meta.verbose_name})"
|
||||||
|
|
||||||
|
|
||||||
class MotionLog(RESTModelMixin, models.Model):
|
class MotionLog(RESTModelMixin, models.Model):
|
||||||
@ -940,12 +927,10 @@ class MotionLog(RESTModelMixin, models.Model):
|
|||||||
"""
|
"""
|
||||||
localtime = timezone.localtime(self.time)
|
localtime = timezone.localtime(self.time)
|
||||||
time = formats.date_format(localtime, "DATETIME_FORMAT")
|
time = formats.date_format(localtime, "DATETIME_FORMAT")
|
||||||
time_and_messages = "%s " % time + "".join(map(_, self.message_list))
|
message_list = "".join(self.message_list)
|
||||||
|
time_and_messages = f"{time} {message_list}"
|
||||||
if self.person is not None:
|
if self.person is not None:
|
||||||
return _("%(time_and_messages)s by %(person)s") % {
|
return f"{time_and_messages} by {self.person}"
|
||||||
"time_and_messages": time_and_messages,
|
|
||||||
"person": self.person,
|
|
||||||
}
|
|
||||||
return time_and_messages
|
return time_and_messages
|
||||||
|
|
||||||
def get_root_rest_element(self):
|
def get_root_rest_element(self):
|
||||||
@ -1016,7 +1001,7 @@ class MotionPoll(RESTModelMixin, CollectDefaultVotesMixin, BasePoll): # type: i
|
|||||||
"""
|
"""
|
||||||
Representation method only for debugging purposes.
|
Representation method only for debugging purposes.
|
||||||
"""
|
"""
|
||||||
return "MotionPoll for motion %s" % self.motion
|
return f"MotionPoll for motion {self.motion}"
|
||||||
|
|
||||||
def set_options(self, skip_autoupdate=False):
|
def set_options(self, skip_autoupdate=False):
|
||||||
"""Create the option class for this poll."""
|
"""Create the option class for this poll."""
|
||||||
@ -1027,9 +1012,6 @@ class MotionPoll(RESTModelMixin, CollectDefaultVotesMixin, BasePoll): # type: i
|
|||||||
def get_percent_base_choice(self):
|
def get_percent_base_choice(self):
|
||||||
return config["motions_poll_100_percent_base"]
|
return config["motions_poll_100_percent_base"]
|
||||||
|
|
||||||
def get_slide_context(self, **context):
|
|
||||||
return super(MotionPoll, self).get_slide_context(poll=self)
|
|
||||||
|
|
||||||
def get_root_rest_element(self):
|
def get_root_rest_element(self):
|
||||||
"""
|
"""
|
||||||
Returns the motion to this instance which is the root REST element.
|
Returns the motion to this instance which is the root REST element.
|
||||||
@ -1145,8 +1127,8 @@ class State(RESTModelMixin, models.Model):
|
|||||||
self.check_next_states()
|
self.check_next_states()
|
||||||
if self.recommendation_label == "":
|
if self.recommendation_label == "":
|
||||||
raise WorkflowError(
|
raise WorkflowError(
|
||||||
"The field recommendation_label of {} must not "
|
f"The field recommendation_label of {self} must not "
|
||||||
"be an empty string.".format(self)
|
"be an empty string."
|
||||||
)
|
)
|
||||||
super(State, self).save(**kwargs)
|
super(State, self).save(**kwargs)
|
||||||
|
|
||||||
@ -1158,8 +1140,7 @@ class State(RESTModelMixin, models.Model):
|
|||||||
for state in self.next_states.all():
|
for state in self.next_states.all():
|
||||||
if not state.workflow == self.workflow:
|
if not state.workflow == self.workflow:
|
||||||
raise WorkflowError(
|
raise WorkflowError(
|
||||||
"%s can not be next state of %s because it does not belong to the same workflow."
|
f"{state} can not be next state of {self} because it does not belong to the same workflow."
|
||||||
% (state, self)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_root_rest_element(self):
|
def get_root_rest_element(self):
|
||||||
@ -1223,6 +1204,6 @@ class Workflow(RESTModelMixin, models.Model):
|
|||||||
"""Checks whether the first_state itself belongs to the workflow."""
|
"""Checks whether the first_state itself belongs to the workflow."""
|
||||||
if self.first_state and not self.first_state.workflow == self:
|
if self.first_state and not self.first_state.workflow == self:
|
||||||
raise WorkflowError(
|
raise WorkflowError(
|
||||||
"%s can not be first state of %s because it "
|
f"{self.first_state} can not be first state of {self} because it "
|
||||||
"does not belong to it." % (self.first_state, self)
|
"does not belong to it."
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
from typing import Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
|
|
||||||
from ..poll.serializers import default_votes_validator
|
from ..poll.serializers import default_votes_validator
|
||||||
from ..utils.auth import get_group_model
|
from ..utils.auth import get_group_model
|
||||||
@ -39,9 +38,7 @@ def validate_workflow_field(value):
|
|||||||
Validator to ensure that the workflow with the given id exists.
|
Validator to ensure that the workflow with the given id exists.
|
||||||
"""
|
"""
|
||||||
if not Workflow.objects.filter(pk=value).exists():
|
if not Workflow.objects.filter(pk=value).exists():
|
||||||
raise ValidationError(
|
raise ValidationError({"detail": f"Workflow {value} does not exist."})
|
||||||
{"detail": _("Workflow %(pk)d does not exist.") % {"pk": value}}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class StatuteParagraphSerializer(ModelSerializer):
|
class StatuteParagraphSerializer(ModelSerializer):
|
||||||
@ -163,10 +160,10 @@ class AmendmentParagraphsJSONSerializerField(Field):
|
|||||||
"""
|
"""
|
||||||
Checks that data is a list of strings.
|
Checks that data is a list of strings.
|
||||||
"""
|
"""
|
||||||
if type(data) is not list:
|
if not isinstance(data, list):
|
||||||
raise ValidationError({"detail": "Data must be a list."})
|
raise ValidationError({"detail": "Data must be a list."})
|
||||||
for paragraph in data:
|
for paragraph in data:
|
||||||
if type(paragraph) is not str and paragraph is not None:
|
if not isinstance(paragraph, str) and paragraph is not None:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": "Paragraph must be either a string or null/None."}
|
{"detail": "Paragraph must be either a string or null/None."}
|
||||||
)
|
)
|
||||||
@ -226,7 +223,7 @@ class MotionPollSerializer(ModelSerializer):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
# The following dictionary is just a cache for several votes.
|
# The following dictionary is just a cache for several votes.
|
||||||
self._votes_dicts: Dict[int, Dict[int, int]] = {}
|
self._votes_dicts: Dict[int, Dict[int, int]] = {}
|
||||||
return super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def get_yes(self, obj):
|
def get_yes(self, obj):
|
||||||
try:
|
try:
|
||||||
@ -280,14 +277,13 @@ class MotionPollSerializer(ModelSerializer):
|
|||||||
if len(votes) != len(instance.get_vote_values()):
|
if len(votes) != len(instance.get_vote_values()):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{
|
||||||
"detail": _("You have to submit data for %d vote values.")
|
"detail": f"You have to submit data for {len(instance.get_vote_values())} vote values."
|
||||||
% len(instance.get_vote_values())
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
for vote_value, vote_weight in votes.items():
|
for vote_value in votes.keys():
|
||||||
if vote_value not in instance.get_vote_values():
|
if vote_value not in instance.get_vote_values():
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("Vote value %s is invalid.") % vote_value}
|
{"detail": f"Vote value {vote_value} is invalid."}
|
||||||
)
|
)
|
||||||
instance.set_vote_objects_with_values(
|
instance.set_vote_objects_with_values(
|
||||||
instance.get_options().get(), votes, skip_autoupdate=True
|
instance.get_options().get(), votes, skip_autoupdate=True
|
||||||
@ -459,14 +455,16 @@ class MotionSerializer(ModelSerializer):
|
|||||||
if "amendment_paragraphs" in data:
|
if "amendment_paragraphs" in data:
|
||||||
data["amendment_paragraphs"] = list(
|
data["amendment_paragraphs"] = list(
|
||||||
map(
|
map(
|
||||||
lambda entry: validate_html(entry) if type(entry) is str else None,
|
lambda entry: validate_html(entry)
|
||||||
|
if isinstance(entry, str)
|
||||||
|
else None,
|
||||||
data["amendment_paragraphs"],
|
data["amendment_paragraphs"],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
data["text"] = ""
|
data["text"] = ""
|
||||||
else:
|
else:
|
||||||
if "text" in data and len(data["text"]) == 0:
|
if "text" in data and not data["text"]:
|
||||||
raise ValidationError({"detail": _("This field may not be blank.")})
|
raise ValidationError({"detail": "This field may not be blank."})
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.utils.translation import ugettext_noop
|
|
||||||
|
|
||||||
from .models import State, Workflow
|
from .models import State, Workflow
|
||||||
|
|
||||||
@ -17,7 +16,7 @@ def create_builtin_workflows(sender, **kwargs):
|
|||||||
workflow_1 = Workflow(name="Simple Workflow")
|
workflow_1 = Workflow(name="Simple Workflow")
|
||||||
workflow_1.save(skip_autoupdate=True)
|
workflow_1.save(skip_autoupdate=True)
|
||||||
state_1_1 = State(
|
state_1_1 = State(
|
||||||
name=ugettext_noop("submitted"),
|
name="submitted",
|
||||||
workflow=workflow_1,
|
workflow=workflow_1,
|
||||||
allow_create_poll=True,
|
allow_create_poll=True,
|
||||||
allow_support=True,
|
allow_support=True,
|
||||||
@ -25,7 +24,7 @@ def create_builtin_workflows(sender, **kwargs):
|
|||||||
)
|
)
|
||||||
state_1_1.save(skip_autoupdate=True)
|
state_1_1.save(skip_autoupdate=True)
|
||||||
state_1_2 = State(
|
state_1_2 = State(
|
||||||
name=ugettext_noop("accepted"),
|
name="accepted",
|
||||||
workflow=workflow_1,
|
workflow=workflow_1,
|
||||||
recommendation_label="Acceptance",
|
recommendation_label="Acceptance",
|
||||||
css_class="success",
|
css_class="success",
|
||||||
@ -33,7 +32,7 @@ def create_builtin_workflows(sender, **kwargs):
|
|||||||
)
|
)
|
||||||
state_1_2.save(skip_autoupdate=True)
|
state_1_2.save(skip_autoupdate=True)
|
||||||
state_1_3 = State(
|
state_1_3 = State(
|
||||||
name=ugettext_noop("rejected"),
|
name="rejected",
|
||||||
workflow=workflow_1,
|
workflow=workflow_1,
|
||||||
recommendation_label="Rejection",
|
recommendation_label="Rejection",
|
||||||
css_class="danger",
|
css_class="danger",
|
||||||
@ -41,7 +40,7 @@ def create_builtin_workflows(sender, **kwargs):
|
|||||||
)
|
)
|
||||||
state_1_3.save(skip_autoupdate=True)
|
state_1_3.save(skip_autoupdate=True)
|
||||||
state_1_4 = State(
|
state_1_4 = State(
|
||||||
name=ugettext_noop("not decided"),
|
name="not decided",
|
||||||
workflow=workflow_1,
|
workflow=workflow_1,
|
||||||
recommendation_label="No decision",
|
recommendation_label="No decision",
|
||||||
css_class="default",
|
css_class="default",
|
||||||
@ -55,7 +54,7 @@ def create_builtin_workflows(sender, **kwargs):
|
|||||||
workflow_2 = Workflow(name="Complex Workflow")
|
workflow_2 = Workflow(name="Complex Workflow")
|
||||||
workflow_2.save(skip_autoupdate=True)
|
workflow_2.save(skip_autoupdate=True)
|
||||||
state_2_1 = State(
|
state_2_1 = State(
|
||||||
name=ugettext_noop("published"),
|
name="published",
|
||||||
workflow=workflow_2,
|
workflow=workflow_2,
|
||||||
allow_support=True,
|
allow_support=True,
|
||||||
allow_submitter_edit=True,
|
allow_submitter_edit=True,
|
||||||
@ -63,7 +62,7 @@ def create_builtin_workflows(sender, **kwargs):
|
|||||||
)
|
)
|
||||||
state_2_1.save(skip_autoupdate=True)
|
state_2_1.save(skip_autoupdate=True)
|
||||||
state_2_2 = State(
|
state_2_2 = State(
|
||||||
name=ugettext_noop("permitted"),
|
name="permitted",
|
||||||
workflow=workflow_2,
|
workflow=workflow_2,
|
||||||
recommendation_label="Permission",
|
recommendation_label="Permission",
|
||||||
allow_create_poll=True,
|
allow_create_poll=True,
|
||||||
@ -71,7 +70,7 @@ def create_builtin_workflows(sender, **kwargs):
|
|||||||
)
|
)
|
||||||
state_2_2.save(skip_autoupdate=True)
|
state_2_2.save(skip_autoupdate=True)
|
||||||
state_2_3 = State(
|
state_2_3 = State(
|
||||||
name=ugettext_noop("accepted"),
|
name="accepted",
|
||||||
workflow=workflow_2,
|
workflow=workflow_2,
|
||||||
recommendation_label="Acceptance",
|
recommendation_label="Acceptance",
|
||||||
css_class="success",
|
css_class="success",
|
||||||
@ -79,7 +78,7 @@ def create_builtin_workflows(sender, **kwargs):
|
|||||||
)
|
)
|
||||||
state_2_3.save(skip_autoupdate=True)
|
state_2_3.save(skip_autoupdate=True)
|
||||||
state_2_4 = State(
|
state_2_4 = State(
|
||||||
name=ugettext_noop("rejected"),
|
name="rejected",
|
||||||
workflow=workflow_2,
|
workflow=workflow_2,
|
||||||
recommendation_label="Rejection",
|
recommendation_label="Rejection",
|
||||||
css_class="danger",
|
css_class="danger",
|
||||||
@ -87,14 +86,14 @@ def create_builtin_workflows(sender, **kwargs):
|
|||||||
)
|
)
|
||||||
state_2_4.save(skip_autoupdate=True)
|
state_2_4.save(skip_autoupdate=True)
|
||||||
state_2_5 = State(
|
state_2_5 = State(
|
||||||
name=ugettext_noop("withdrawed"),
|
name="withdrawed",
|
||||||
workflow=workflow_2,
|
workflow=workflow_2,
|
||||||
css_class="default",
|
css_class="default",
|
||||||
merge_amendment_into_final=-1,
|
merge_amendment_into_final=-1,
|
||||||
)
|
)
|
||||||
state_2_5.save(skip_autoupdate=True)
|
state_2_5.save(skip_autoupdate=True)
|
||||||
state_2_6 = State(
|
state_2_6 = State(
|
||||||
name=ugettext_noop("adjourned"),
|
name="adjourned",
|
||||||
workflow=workflow_2,
|
workflow=workflow_2,
|
||||||
recommendation_label="Adjournment",
|
recommendation_label="Adjournment",
|
||||||
css_class="default",
|
css_class="default",
|
||||||
@ -102,7 +101,7 @@ def create_builtin_workflows(sender, **kwargs):
|
|||||||
)
|
)
|
||||||
state_2_6.save(skip_autoupdate=True)
|
state_2_6.save(skip_autoupdate=True)
|
||||||
state_2_7 = State(
|
state_2_7 = State(
|
||||||
name=ugettext_noop("not concerned"),
|
name="not concerned",
|
||||||
workflow=workflow_2,
|
workflow=workflow_2,
|
||||||
recommendation_label="No concernment",
|
recommendation_label="No concernment",
|
||||||
css_class="default",
|
css_class="default",
|
||||||
@ -110,7 +109,7 @@ def create_builtin_workflows(sender, **kwargs):
|
|||||||
)
|
)
|
||||||
state_2_7.save(skip_autoupdate=True)
|
state_2_7.save(skip_autoupdate=True)
|
||||||
state_2_8 = State(
|
state_2_8 = State(
|
||||||
name=ugettext_noop("refered to committee"),
|
name="refered to committee",
|
||||||
workflow=workflow_2,
|
workflow=workflow_2,
|
||||||
recommendation_label="Referral to committee",
|
recommendation_label="Referral to committee",
|
||||||
css_class="default",
|
css_class="default",
|
||||||
@ -118,14 +117,14 @@ def create_builtin_workflows(sender, **kwargs):
|
|||||||
)
|
)
|
||||||
state_2_8.save(skip_autoupdate=True)
|
state_2_8.save(skip_autoupdate=True)
|
||||||
state_2_9 = State(
|
state_2_9 = State(
|
||||||
name=ugettext_noop("needs review"),
|
name="needs review",
|
||||||
workflow=workflow_2,
|
workflow=workflow_2,
|
||||||
css_class="default",
|
css_class="default",
|
||||||
merge_amendment_into_final=-1,
|
merge_amendment_into_final=-1,
|
||||||
)
|
)
|
||||||
state_2_9.save(skip_autoupdate=True)
|
state_2_9.save(skip_autoupdate=True)
|
||||||
state_2_10 = State(
|
state_2_10 = State(
|
||||||
name=ugettext_noop("rejected (not authorized)"),
|
name="rejected (not authorized)",
|
||||||
workflow=workflow_2,
|
workflow=workflow_2,
|
||||||
recommendation_label="Rejection (not authorized)",
|
recommendation_label="Rejection (not authorized)",
|
||||||
css_class="default",
|
css_class="default",
|
||||||
|
@ -8,7 +8,6 @@ from django.core.exceptions import ValidationError as DjangoValidationError
|
|||||||
from django.db import IntegrityError, transaction
|
from django.db import IntegrityError, transaction
|
||||||
from django.db.models.deletion import ProtectedError
|
from django.db.models.deletion import ProtectedError
|
||||||
from django.http.request import QueryDict
|
from django.http.request import QueryDict
|
||||||
from django.utils.translation import ugettext as _, ugettext_noop
|
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
|
||||||
from ..core.config import config
|
from ..core.config import config
|
||||||
@ -149,9 +148,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
try:
|
try:
|
||||||
parent_motion = Motion.objects.get(pk=request.data["parent_id"])
|
parent_motion = Motion.objects.get(pk=request.data["parent_id"])
|
||||||
except Motion.DoesNotExist:
|
except Motion.DoesNotExist:
|
||||||
raise ValidationError(
|
raise ValidationError({"detail": "The parent motion does not exist."})
|
||||||
{"detail": _("The parent motion does not exist.")}
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
parent_motion = None
|
parent_motion = None
|
||||||
|
|
||||||
@ -193,7 +190,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
submitters_id = []
|
submitters_id = []
|
||||||
if not isinstance(submitters_id, list):
|
if not isinstance(submitters_id, list):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("If submitters_id is given, it has to be a list.")}
|
{"detail": "If submitters_id is given, it has to be a list."}
|
||||||
)
|
)
|
||||||
|
|
||||||
submitters_id_unique = set()
|
submitters_id_unique = set()
|
||||||
@ -211,7 +208,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
continue # Do not add users that do not exist
|
continue # Do not add users that do not exist
|
||||||
|
|
||||||
# Add the request user, if he is authenticated and no submitters were given:
|
# Add the request user, if he is authenticated and no submitters were given:
|
||||||
if len(submitters) == 0 and request.user.is_authenticated:
|
if not submitters and request.user.is_authenticated:
|
||||||
submitters.append(request.user)
|
submitters.append(request.user)
|
||||||
|
|
||||||
# create all submitters
|
# create all submitters
|
||||||
@ -219,7 +216,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
Submitter.objects.add(submitter, motion)
|
Submitter.objects.add(submitter, motion)
|
||||||
|
|
||||||
# Write the log message and initiate response.
|
# Write the log message and initiate response.
|
||||||
motion.write_log([ugettext_noop("Motion created")], request.user)
|
motion.write_log(["Motion created"], request.user)
|
||||||
|
|
||||||
# Send new submitters and supporters via autoupdate because users
|
# Send new submitters and supporters via autoupdate because users
|
||||||
# without permission to see users may not have them but can get it now.
|
# without permission to see users may not have them but can get it now.
|
||||||
@ -289,16 +286,14 @@ class MotionViewSet(ModelViewSet):
|
|||||||
|
|
||||||
# Write the log message, check removal of supporters and initiate response.
|
# Write the log message, check removal of supporters and initiate response.
|
||||||
# TODO: Log if a motion was updated.
|
# TODO: Log if a motion was updated.
|
||||||
updated_motion.write_log([ugettext_noop("Motion updated")], request.user)
|
updated_motion.write_log(["Motion updated"], request.user)
|
||||||
if (
|
if (
|
||||||
config["motions_remove_supporters"]
|
config["motions_remove_supporters"]
|
||||||
and updated_motion.state.allow_support
|
and updated_motion.state.allow_support
|
||||||
and not has_perm(request.user, "motions.can_manage")
|
and not has_perm(request.user, "motions.can_manage")
|
||||||
):
|
):
|
||||||
updated_motion.supporters.clear()
|
updated_motion.supporters.clear()
|
||||||
updated_motion.write_log(
|
updated_motion.write_log(["All supporters removed"], request.user)
|
||||||
[ugettext_noop("All supporters removed")], request.user
|
|
||||||
)
|
|
||||||
|
|
||||||
# Send new supporters via autoupdate because users
|
# Send new supporters via autoupdate because users
|
||||||
# without permission to see users may not have them but can get it now.
|
# without permission to see users may not have them but can get it now.
|
||||||
@ -339,12 +334,12 @@ class MotionViewSet(ModelViewSet):
|
|||||||
while ancestor is not None:
|
while ancestor is not None:
|
||||||
if ancestor == motion:
|
if ancestor == motion:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("There must not be a hierarchical loop.")}
|
{"detail": "There must not be a hierarchical loop."}
|
||||||
)
|
)
|
||||||
ancestor = ancestor.sort_parent
|
ancestor = ancestor.sort_parent
|
||||||
|
|
||||||
inform_changed_data(motions)
|
inform_changed_data(motions)
|
||||||
return Response({"detail": _("The motions has been sorted.")})
|
return Response({"detail": "The motions has been sorted."})
|
||||||
|
|
||||||
@detail_route(methods=["POST", "DELETE"])
|
@detail_route(methods=["POST", "DELETE"])
|
||||||
def manage_comments(self, request, pk=None):
|
def manage_comments(self, request, pk=None):
|
||||||
@ -363,18 +358,14 @@ class MotionViewSet(ModelViewSet):
|
|||||||
section_id = request.data.get("section_id")
|
section_id = request.data.get("section_id")
|
||||||
if not section_id or not isinstance(section_id, int):
|
if not section_id or not isinstance(section_id, int):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("You have to provide a section_id of type int.")}
|
{"detail": "You have to provide a section_id of type int."}
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
section = MotionCommentSection.objects.get(pk=section_id)
|
section = MotionCommentSection.objects.get(pk=section_id)
|
||||||
except MotionCommentSection.DoesNotExist:
|
except MotionCommentSection.DoesNotExist:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{"detail": f"A comment section with id {section_id} does not exist."}
|
||||||
"detail": _("A comment section with id {} does not exist").format(
|
|
||||||
section_id
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# the request user needs to see and write to the comment section
|
# the request user needs to see and write to the comment section
|
||||||
@ -385,9 +376,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
):
|
):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{
|
||||||
"detail": _(
|
"detail": "You are not allowed to see or write to the comment section."
|
||||||
"You are not allowed to see or write to the comment section."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -395,7 +384,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
# validate comment
|
# validate comment
|
||||||
comment_value = request.data.get("comment", "")
|
comment_value = request.data.get("comment", "")
|
||||||
if not isinstance(comment_value, str):
|
if not isinstance(comment_value, str):
|
||||||
raise ValidationError({"detail": _("The comment should be a string.")})
|
raise ValidationError({"detail": "The comment should be a string."})
|
||||||
|
|
||||||
comment, created = MotionComment.objects.get_or_create(
|
comment, created = MotionComment.objects.get_or_create(
|
||||||
motion=motion, section=section, defaults={"comment": comment_value}
|
motion=motion, section=section, defaults={"comment": comment_value}
|
||||||
@ -405,10 +394,8 @@ class MotionViewSet(ModelViewSet):
|
|||||||
comment.save()
|
comment.save()
|
||||||
|
|
||||||
# write log
|
# write log
|
||||||
motion.write_log(
|
motion.write_log([f"Comment {section.name} updated"], request.user)
|
||||||
[ugettext_noop("Comment {} updated").format(section.name)], request.user
|
message = f"Comment {section.name} updated"
|
||||||
)
|
|
||||||
message = _("Comment {} updated").format(section.name)
|
|
||||||
else: # DELETE
|
else: # DELETE
|
||||||
try:
|
try:
|
||||||
comment = MotionComment.objects.get(motion=motion, section=section)
|
comment = MotionComment.objects.get(motion=motion, section=section)
|
||||||
@ -418,11 +405,8 @@ class MotionViewSet(ModelViewSet):
|
|||||||
else:
|
else:
|
||||||
comment.delete()
|
comment.delete()
|
||||||
|
|
||||||
motion.write_log(
|
motion.write_log([f"Comment {section.name} deleted"], request.user)
|
||||||
[ugettext_noop("Comment {} deleted").format(section.name)],
|
message = f"Comment {section.name} deleted"
|
||||||
request.user,
|
|
||||||
)
|
|
||||||
message = _("Comment {} deleted").format(section.name)
|
|
||||||
|
|
||||||
return Response({"detail": message})
|
return Response({"detail": message})
|
||||||
|
|
||||||
@ -470,9 +454,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
try:
|
try:
|
||||||
motion = Motion.objects.get(pk=item["id"])
|
motion = Motion.objects.get(pk=item["id"])
|
||||||
except Motion.DoesNotExist:
|
except Motion.DoesNotExist:
|
||||||
raise ValidationError(
|
raise ValidationError({"detail": f"Motion {item['id']} does not exist"})
|
||||||
{"detail": "Motion {} does not exist".format(item["id"])}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Remove all submitters.
|
# Remove all submitters.
|
||||||
Submitter.objects.filter(motion=motion).delete()
|
Submitter.objects.filter(motion=motion).delete()
|
||||||
@ -483,7 +465,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
submitter = get_user_model().objects.get(pk=submitter_id)
|
submitter = get_user_model().objects.get(pk=submitter_id)
|
||||||
except get_user_model().DoesNotExist:
|
except get_user_model().DoesNotExist:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": "Submitter {} does not exist".format(submitter_id)}
|
{"detail": f"Submitter {submitter_id} does not exist"}
|
||||||
)
|
)
|
||||||
Submitter.objects.add(submitter, motion)
|
Submitter.objects.add(submitter, motion)
|
||||||
new_submitters.append(submitter)
|
new_submitters.append(submitter)
|
||||||
@ -501,11 +483,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
|
|
||||||
# Send response.
|
# Send response.
|
||||||
return Response(
|
return Response(
|
||||||
{
|
{"detail": f"{len(motion_result)} motions successfully updated."}
|
||||||
"detail": _("{number} motions successfully updated.").format(
|
|
||||||
number=len(motion_result)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@detail_route(methods=["post", "delete"])
|
@detail_route(methods=["post", "delete"])
|
||||||
@ -528,23 +506,21 @@ class MotionViewSet(ModelViewSet):
|
|||||||
and not motion.is_submitter(request.user)
|
and not motion.is_submitter(request.user)
|
||||||
and not motion.is_supporter(request.user)
|
and not motion.is_supporter(request.user)
|
||||||
):
|
):
|
||||||
raise ValidationError({"detail": _("You can not support this motion.")})
|
raise ValidationError({"detail": "You can not support this motion."})
|
||||||
motion.supporters.add(request.user)
|
motion.supporters.add(request.user)
|
||||||
motion.write_log([ugettext_noop("Motion supported")], request.user)
|
motion.write_log(["Motion supported"], request.user)
|
||||||
# Send new supporter via autoupdate because users without permission
|
# Send new supporter via autoupdate because users without permission
|
||||||
# to see users may not have it but can get it now.
|
# to see users may not have it but can get it now.
|
||||||
inform_changed_data([request.user])
|
inform_changed_data([request.user])
|
||||||
message = _("You have supported this motion successfully.")
|
message = "You have supported this motion successfully."
|
||||||
else:
|
else:
|
||||||
# Unsupport motion.
|
# Unsupport motion.
|
||||||
# request.method == 'DELETE'
|
# request.method == 'DELETE'
|
||||||
if not motion.state.allow_support or not motion.is_supporter(request.user):
|
if not motion.state.allow_support or not motion.is_supporter(request.user):
|
||||||
raise ValidationError(
|
raise ValidationError({"detail": "You can not unsupport this motion."})
|
||||||
{"detail": _("You can not unsupport this motion.")}
|
|
||||||
)
|
|
||||||
motion.supporters.remove(request.user)
|
motion.supporters.remove(request.user)
|
||||||
motion.write_log([ugettext_noop("Motion unsupported")], request.user)
|
motion.write_log(["Motion unsupported"], request.user)
|
||||||
message = _("You have unsupported this motion successfully.")
|
message = "You have unsupported this motion successfully."
|
||||||
|
|
||||||
# Initiate response.
|
# Initiate response.
|
||||||
return Response({"detail": message})
|
return Response({"detail": message})
|
||||||
@ -568,14 +544,11 @@ class MotionViewSet(ModelViewSet):
|
|||||||
state_id = int(state)
|
state_id = int(state)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("Invalid data. State must be an integer.")}
|
{"detail": "Invalid data. State must be an integer."}
|
||||||
)
|
)
|
||||||
if state_id not in [item.id for item in motion.state.next_states.all()]:
|
if state_id not in [item.id for item in motion.state.next_states.all()]:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{"detail": f"You can not set the state to {state_id}."}
|
||||||
"detail": _("You can not set the state to %(state_id)d.")
|
|
||||||
% {"state_id": state_id}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
motion.set_state(state_id)
|
motion.set_state(state_id)
|
||||||
else:
|
else:
|
||||||
@ -587,17 +560,15 @@ class MotionViewSet(ModelViewSet):
|
|||||||
update_fields=["state", "identifier", "identifier_number"],
|
update_fields=["state", "identifier", "identifier_number"],
|
||||||
skip_autoupdate=True,
|
skip_autoupdate=True,
|
||||||
)
|
)
|
||||||
message = _("The state of the motion was set to %s.") % motion.state.name
|
message = f"The state of the motion was set to {motion.state.name}."
|
||||||
|
|
||||||
# Write the log message and initiate response.
|
# Write the log message and initiate response.
|
||||||
motion.write_log(
|
motion.write_log(
|
||||||
message_list=[ugettext_noop("State set to"), " ", motion.state.name],
|
message_list=[f"State set to {motion.state.name}"],
|
||||||
person=request.user,
|
person=request.user,
|
||||||
skip_autoupdate=True,
|
skip_autoupdate=True,
|
||||||
)
|
)
|
||||||
inform_changed_data(
|
inform_changed_data(motion, information=f"State set to {motion.state.name}.")
|
||||||
motion, information="State set to {}.".format(motion.state.name)
|
|
||||||
)
|
|
||||||
return Response({"detail": message})
|
return Response({"detail": message})
|
||||||
|
|
||||||
@detail_route(methods=["put"])
|
@detail_route(methods=["put"])
|
||||||
@ -619,7 +590,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
recommendation_state_id = int(recommendation_state)
|
recommendation_state_id = int(recommendation_state)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("Invalid data. Recommendation must be an integer.")}
|
{"detail": "Invalid data. Recommendation must be an integer."}
|
||||||
)
|
)
|
||||||
recommendable_states = State.objects.filter(
|
recommendable_states = State.objects.filter(
|
||||||
workflow=motion.workflow_id, recommendation_label__isnull=False
|
workflow=motion.workflow_id, recommendation_label__isnull=False
|
||||||
@ -629,9 +600,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
]:
|
]:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{
|
||||||
"detail": _(
|
"detail": f"You can not set the recommendation to {recommendation_state_id}."
|
||||||
"You can not set the recommendation to {recommendation_state_id}."
|
|
||||||
).format(recommendation_state_id=recommendation_state_id)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
motion.set_recommendation(recommendation_state_id)
|
motion.set_recommendation(recommendation_state_id)
|
||||||
@ -646,11 +615,11 @@ class MotionViewSet(ModelViewSet):
|
|||||||
if motion.recommendation
|
if motion.recommendation
|
||||||
else "None"
|
else "None"
|
||||||
)
|
)
|
||||||
message = _("The recommendation of the motion was set to %s.") % label
|
message = f"The recommendation of the motion was set to {label}."
|
||||||
|
|
||||||
# Write the log message and initiate response.
|
# Write the log message and initiate response.
|
||||||
motion.write_log(
|
motion.write_log(
|
||||||
message_list=[ugettext_noop("Recommendation set to"), " ", label],
|
message_list=["Recommendation set to", " ", label],
|
||||||
person=request.user,
|
person=request.user,
|
||||||
skip_autoupdate=True,
|
skip_autoupdate=True,
|
||||||
)
|
)
|
||||||
@ -698,9 +667,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
try:
|
try:
|
||||||
motion = Motion.objects.get(pk=item["id"])
|
motion = Motion.objects.get(pk=item["id"])
|
||||||
except Motion.DoesNotExist:
|
except Motion.DoesNotExist:
|
||||||
raise ValidationError(
|
raise ValidationError({"detail": f"Motion {item['id']} does not exist"})
|
||||||
{"detail": "Motion {} does not exist".format(item["id"])}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Set or reset recommendation.
|
# Set or reset recommendation.
|
||||||
recommendation_state_id = item["recommendation"]
|
recommendation_state_id = item["recommendation"]
|
||||||
@ -717,9 +684,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
]:
|
]:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{
|
||||||
"detail": _(
|
"detail": "You can not set the recommendation to {recommendation_state_id}."
|
||||||
"You can not set the recommendation to {recommendation_state_id}."
|
|
||||||
).format(recommendation_state_id=recommendation_state_id)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
motion.set_recommendation(recommendation_state_id)
|
motion.set_recommendation(recommendation_state_id)
|
||||||
@ -734,7 +699,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
|
|
||||||
# Write the log message.
|
# Write the log message.
|
||||||
motion.write_log(
|
motion.write_log(
|
||||||
message_list=[ugettext_noop("Recommendation set to"), " ", label],
|
message_list=["Recommendation set to", " ", label],
|
||||||
person=request.user,
|
person=request.user,
|
||||||
skip_autoupdate=True,
|
skip_autoupdate=True,
|
||||||
)
|
)
|
||||||
@ -747,18 +712,14 @@ class MotionViewSet(ModelViewSet):
|
|||||||
|
|
||||||
# Send response.
|
# Send response.
|
||||||
return Response(
|
return Response(
|
||||||
{
|
{"detail": f"{len(motion_result)} motions successfully updated."}
|
||||||
"detail": _("{number} motions successfully updated.").format(
|
|
||||||
number=len(motion_result)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@detail_route(methods=["post"])
|
@detail_route(methods=["post"])
|
||||||
def follow_recommendation(self, request, pk=None):
|
def follow_recommendation(self, request, pk=None):
|
||||||
motion = self.get_object()
|
motion = self.get_object()
|
||||||
if motion.recommendation is None:
|
if motion.recommendation is None:
|
||||||
raise ValidationError({"detail": _("Cannot set an empty recommendation.")})
|
raise ValidationError({"detail": "Cannot set an empty recommendation."})
|
||||||
|
|
||||||
# Set state.
|
# Set state.
|
||||||
motion.set_state(motion.recommendation)
|
motion.set_state(motion.recommendation)
|
||||||
@ -779,7 +740,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
skip_autoupdate=True,
|
skip_autoupdate=True,
|
||||||
)
|
)
|
||||||
motion.write_log(
|
motion.write_log(
|
||||||
message_list=[ugettext_noop("State set to"), " ", motion.state.name],
|
message_list=["State set to", " ", motion.state.name],
|
||||||
person=request.user,
|
person=request.user,
|
||||||
skip_autoupdate=True,
|
skip_autoupdate=True,
|
||||||
)
|
)
|
||||||
@ -801,15 +762,13 @@ class MotionViewSet(ModelViewSet):
|
|||||||
try:
|
try:
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
poll = motion.create_poll(skip_autoupdate=True)
|
poll = motion.create_poll(skip_autoupdate=True)
|
||||||
except WorkflowError as e:
|
except WorkflowError as err:
|
||||||
raise ValidationError({"detail": e})
|
raise ValidationError({"detail": err})
|
||||||
motion.write_log(
|
motion.write_log(["Vote created"], request.user, skip_autoupdate=True)
|
||||||
[ugettext_noop("Vote created")], request.user, skip_autoupdate=True
|
|
||||||
)
|
|
||||||
|
|
||||||
inform_changed_data(motion)
|
inform_changed_data(motion)
|
||||||
return Response(
|
return Response(
|
||||||
{"detail": _("Vote created successfully."), "createdPollId": poll.pk}
|
{"detail": "Vote created successfully.", "createdPollId": poll.pk}
|
||||||
)
|
)
|
||||||
|
|
||||||
@list_route(methods=["post"])
|
@list_route(methods=["post"])
|
||||||
@ -855,16 +814,12 @@ class MotionViewSet(ModelViewSet):
|
|||||||
try:
|
try:
|
||||||
motion = Motion.objects.get(pk=item["id"])
|
motion = Motion.objects.get(pk=item["id"])
|
||||||
except Motion.DoesNotExist:
|
except Motion.DoesNotExist:
|
||||||
raise ValidationError(
|
raise ValidationError({"detail": f"Motion {item['id']} does not exist"})
|
||||||
{"detail": "Motion {} does not exist".format(item["id"])}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Set new tags
|
# Set new tags
|
||||||
for tag_id in item["tags"]:
|
for tag_id in item["tags"]:
|
||||||
if not Tag.objects.filter(pk=tag_id).exists():
|
if not Tag.objects.filter(pk=tag_id).exists():
|
||||||
raise ValidationError(
|
raise ValidationError({"detail": f"Tag {tag_id} does not exist"})
|
||||||
{"detail": "Tag {} does not exist".format(tag_id)}
|
|
||||||
)
|
|
||||||
motion.tags.set(item["tags"])
|
motion.tags.set(item["tags"])
|
||||||
|
|
||||||
# Finish motion.
|
# Finish motion.
|
||||||
@ -875,11 +830,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
|
|
||||||
# Send response.
|
# Send response.
|
||||||
return Response(
|
return Response(
|
||||||
{
|
{"detail": f"{len(motion_result)} motions successfully updated."}
|
||||||
"detail": _("{number} motions successfully updated.").format(
|
|
||||||
number=len(motion_result)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -907,7 +858,7 @@ class MotionPollViewSet(UpdateModelMixin, DestroyModelMixin, GenericViewSet):
|
|||||||
"""
|
"""
|
||||||
response = super().update(*args, **kwargs)
|
response = super().update(*args, **kwargs)
|
||||||
poll = self.get_object()
|
poll = self.get_object()
|
||||||
poll.motion.write_log([ugettext_noop("Vote updated")], self.request.user)
|
poll.motion.write_log(["Vote updated"], self.request.user)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def destroy(self, *args, **kwargs):
|
def destroy(self, *args, **kwargs):
|
||||||
@ -916,7 +867,7 @@ class MotionPollViewSet(UpdateModelMixin, DestroyModelMixin, GenericViewSet):
|
|||||||
"""
|
"""
|
||||||
poll = self.get_object()
|
poll = self.get_object()
|
||||||
result = super().destroy(*args, **kwargs)
|
result = super().destroy(*args, **kwargs)
|
||||||
poll.motion.write_log([ugettext_noop("Vote deleted")], self.request.user)
|
poll.motion.write_log(["Vote deleted"], self.request.user)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@ -986,26 +937,20 @@ class MotionCommentSectionViewSet(ModelViewSet):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
result = super().destroy(*args, **kwargs)
|
result = super().destroy(*args, **kwargs)
|
||||||
except ProtectedError as e:
|
except ProtectedError as err:
|
||||||
# The protected objects can just be motion comments.
|
# The protected objects can just be motion comments.
|
||||||
motions = [
|
motions = [f'"{comment.motion}"' for comment in err.protected_objects.all()]
|
||||||
'"' + str(comment.motion) + '"' for comment in e.protected_objects.all()
|
|
||||||
]
|
|
||||||
count = len(motions)
|
count = len(motions)
|
||||||
motions_verbose = ", ".join(motions[:3])
|
motions_verbose = ", ".join(motions[:3])
|
||||||
if count > 3:
|
if count > 3:
|
||||||
motions_verbose += ", ..."
|
motions_verbose += ", ..."
|
||||||
|
|
||||||
if count == 1:
|
if count == 1:
|
||||||
msg = _("This section has still comments in motion {}.").format(
|
msg = f"This section has still comments in motion {motions_verbose}."
|
||||||
motions_verbose
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
msg = _("This section has still comments in motions {}.").format(
|
msg = f"This section has still comments in motions {motions_verbose}."
|
||||||
motions_verbose
|
|
||||||
)
|
|
||||||
|
|
||||||
msg += " " + _("Please remove all comments before deletion.")
|
msg += " " + "Please remove all comments before deletion."
|
||||||
raise ValidationError({"detail": msg})
|
raise ValidationError({"detail": msg})
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -1098,9 +1043,9 @@ class CategoryViewSet(ModelViewSet):
|
|||||||
if not category.prefix:
|
if not category.prefix:
|
||||||
prefix = ""
|
prefix = ""
|
||||||
elif without_blank:
|
elif without_blank:
|
||||||
prefix = "%s" % category.prefix
|
prefix = category.prefix
|
||||||
else:
|
else:
|
||||||
prefix = "%s " % category.prefix
|
prefix = f"{category.prefix} "
|
||||||
motions = category.motion_set.all()
|
motions = category.motion_set.all()
|
||||||
motion_list = request.data.get("motions")
|
motion_list = request.data.get("motions")
|
||||||
if motion_list:
|
if motion_list:
|
||||||
@ -1119,19 +1064,12 @@ class CategoryViewSet(ModelViewSet):
|
|||||||
if motion.is_amendment():
|
if motion.is_amendment():
|
||||||
parent_identifier = motion.parent.identifier or ""
|
parent_identifier = motion.parent.identifier or ""
|
||||||
if without_blank:
|
if without_blank:
|
||||||
prefix = "%s%s" % (
|
prefix = f"{parent_identifier}{config['motions_amendments_prefix']}"
|
||||||
parent_identifier,
|
|
||||||
config["motions_amendments_prefix"],
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
prefix = "%s %s " % (
|
prefix = f"{parent_identifier} {config['motions_amendments_prefix']} "
|
||||||
parent_identifier,
|
|
||||||
config["motions_amendments_prefix"],
|
|
||||||
)
|
|
||||||
number += 1
|
number += 1
|
||||||
new_identifier = "%s%s" % (
|
new_identifier = (
|
||||||
prefix,
|
f"{prefix}{motion.extend_identifier_number(number)}"
|
||||||
motion.extend_identifier_number(number),
|
|
||||||
)
|
)
|
||||||
motions_to_be_sorted.append(
|
motions_to_be_sorted.append(
|
||||||
{
|
{
|
||||||
@ -1153,13 +1091,11 @@ class CategoryViewSet(ModelViewSet):
|
|||||||
for obj in motions_to_be_sorted:
|
for obj in motions_to_be_sorted:
|
||||||
if Motion.objects.filter(identifier=obj["new_identifier"]).exists():
|
if Motion.objects.filter(identifier=obj["new_identifier"]).exists():
|
||||||
# Set the error message and let the code run into an IntegrityError
|
# Set the error message and let the code run into an IntegrityError
|
||||||
|
new_identifier = obj["new_identifier"]
|
||||||
error_message = (
|
error_message = (
|
||||||
_(
|
f'Numbering aborted because the motion identifier "{new_identifier}" '
|
||||||
'Numbering aborted because the motion identifier "%s" '
|
|
||||||
"already exists outside of this category."
|
"already exists outside of this category."
|
||||||
)
|
)
|
||||||
% obj["new_identifier"]
|
|
||||||
)
|
|
||||||
motion = obj["motion"]
|
motion = obj["motion"]
|
||||||
motion.identifier = obj["new_identifier"]
|
motion.identifier = obj["new_identifier"]
|
||||||
motion.identifier_number = obj["number"]
|
motion.identifier_number = obj["number"]
|
||||||
@ -1186,16 +1122,11 @@ class CategoryViewSet(ModelViewSet):
|
|||||||
instances.append(child.agenda_item)
|
instances.append(child.agenda_item)
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
if error_message is None:
|
if error_message is None:
|
||||||
error_message = _(
|
error_message = "Error: At least one identifier of this category does already exist in another category."
|
||||||
"Error: At least one identifier of this category does "
|
|
||||||
"already exist in another category."
|
|
||||||
)
|
|
||||||
response = Response({"detail": error_message}, status=400)
|
response = Response({"detail": error_message}, status=400)
|
||||||
else:
|
else:
|
||||||
inform_changed_data(instances)
|
inform_changed_data(instances)
|
||||||
message = _(
|
message = f"All motions in category {category} numbered " "successfully."
|
||||||
"All motions in category {category} numbered " "successfully."
|
|
||||||
).format(category=category)
|
|
||||||
response = Response({"detail": message})
|
response = Response({"detail": message})
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@ -1248,17 +1179,13 @@ class MotionBlockViewSet(ModelViewSet):
|
|||||||
motion.save(skip_autoupdate=True)
|
motion.save(skip_autoupdate=True)
|
||||||
# Write the log message.
|
# Write the log message.
|
||||||
motion.write_log(
|
motion.write_log(
|
||||||
message_list=[
|
message_list=["State set to", " ", motion.state.name],
|
||||||
ugettext_noop("State set to"),
|
|
||||||
" ",
|
|
||||||
motion.state.name,
|
|
||||||
],
|
|
||||||
person=request.user,
|
person=request.user,
|
||||||
skip_autoupdate=True,
|
skip_autoupdate=True,
|
||||||
)
|
)
|
||||||
instances.append(motion)
|
instances.append(motion)
|
||||||
inform_changed_data(instances)
|
inform_changed_data(instances)
|
||||||
return Response({"detail": _("Followed recommendations successfully.")})
|
return Response({"detail": "Followed recommendations successfully."})
|
||||||
|
|
||||||
|
|
||||||
class ProtectedErrorMessageMixin:
|
class ProtectedErrorMessageMixin:
|
||||||
@ -1271,10 +1198,10 @@ class ProtectedErrorMessageMixin:
|
|||||||
motions_verbose += ", ..."
|
motions_verbose += ", ..."
|
||||||
|
|
||||||
if count == 1:
|
if count == 1:
|
||||||
msg = _("This {} is assigned to motion {}.").format(name, motions_verbose)
|
msg = f"This {name} is assigned to motion {motions_verbose}."
|
||||||
else:
|
else:
|
||||||
msg = _("This {} is assigned to motions {}.").format(name, motions_verbose)
|
msg = f"This {name} is assigned to motions {motions_verbose}."
|
||||||
return msg + " " + _("Please remove all assignments before deletion.")
|
return f"{msg} Please remove all assignments before deletion."
|
||||||
|
|
||||||
|
|
||||||
class WorkflowViewSet(ModelViewSet, ProtectedErrorMessageMixin):
|
class WorkflowViewSet(ModelViewSet, ProtectedErrorMessageMixin):
|
||||||
@ -1310,8 +1237,8 @@ class WorkflowViewSet(ModelViewSet, ProtectedErrorMessageMixin):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
result = super().destroy(*args, **kwargs)
|
result = super().destroy(*args, **kwargs)
|
||||||
except ProtectedError as e:
|
except ProtectedError as err:
|
||||||
msg = self.getProtectedErrorMessage("workflow", e)
|
msg = self.getProtectedErrorMessage("workflow", err)
|
||||||
raise ValidationError({"detail": msg})
|
raise ValidationError({"detail": msg})
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -1349,11 +1276,11 @@ class StateViewSet(
|
|||||||
state.workflow.first_state.pk == state.pk
|
state.workflow.first_state.pk == state.pk
|
||||||
): # is this the first state of the workflow?
|
): # is this the first state of the workflow?
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("You cannot delete the first state of the workflow.")}
|
{"detail": "You cannot delete the first state of the workflow."}
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
result = super().destroy(*args, **kwargs)
|
result = super().destroy(*args, **kwargs)
|
||||||
except ProtectedError as e:
|
except ProtectedError as err:
|
||||||
msg = self.getProtectedErrorMessage("workflow", e)
|
msg = self.getProtectedErrorMessage("workflow", err)
|
||||||
raise ValidationError({"detail": msg})
|
raise ValidationError({"detail": msg})
|
||||||
return result
|
return result
|
||||||
|
@ -5,7 +5,6 @@ from typing import Optional, Type
|
|||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.core.validators import MinValueValidator
|
from django.core.validators import MinValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
|
|
||||||
|
|
||||||
class BaseOption(models.Model):
|
class BaseOption(models.Model):
|
||||||
@ -29,7 +28,7 @@ class BaseOption(models.Model):
|
|||||||
def get_vote_class(self):
|
def get_vote_class(self):
|
||||||
if self.vote_class is None:
|
if self.vote_class is None:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"The option class %s has to have an attribute vote_class." % self
|
f"The option class {self} has to have an attribute vote_class."
|
||||||
)
|
)
|
||||||
return self.vote_class
|
return self.vote_class
|
||||||
|
|
||||||
@ -64,7 +63,7 @@ class BaseVote(models.Model):
|
|||||||
return self.print_weight()
|
return self.print_weight()
|
||||||
|
|
||||||
def get_value(self):
|
def get_value(self):
|
||||||
return _(self.value)
|
return self.value
|
||||||
|
|
||||||
def print_weight(self, raw=False):
|
def print_weight(self, raw=False):
|
||||||
if raw:
|
if raw:
|
||||||
@ -150,12 +149,15 @@ class BasePoll(models.Model):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def set_options(self, options_data=[], skip_autoupdate=False):
|
def set_options(self, options_data=None, skip_autoupdate=False):
|
||||||
"""
|
"""
|
||||||
Adds new option objects to the poll.
|
Adds new option objects to the poll.
|
||||||
|
|
||||||
option_data: A list of arguments for the option.
|
option_data: A list of arguments for the option.
|
||||||
"""
|
"""
|
||||||
|
if options_data is None:
|
||||||
|
options_data = []
|
||||||
|
|
||||||
for option_data in options_data:
|
for option_data in options_data:
|
||||||
option = self.get_option_class()(**option_data)
|
option = self.get_option_class()(**option_data)
|
||||||
option.poll = self
|
option.poll = self
|
||||||
@ -224,11 +226,11 @@ def print_value(value, percent_base=0):
|
|||||||
'undocumented' or the vote value with percent value if so.
|
'undocumented' or the vote value with percent value if so.
|
||||||
"""
|
"""
|
||||||
if value == -1:
|
if value == -1:
|
||||||
verbose_value = _("majority")
|
verbose_value = "majority"
|
||||||
elif value == -2:
|
elif value == -2:
|
||||||
verbose_value = _("undocumented")
|
verbose_value = "undocumented"
|
||||||
elif value is None:
|
elif value is None:
|
||||||
verbose_value = _("undocumented")
|
verbose_value = "undocumented"
|
||||||
else:
|
else:
|
||||||
if percent_base:
|
if percent_base:
|
||||||
locale.setlocale(locale.LC_ALL, "")
|
locale.setlocale(locale.LC_ALL, "")
|
||||||
@ -237,5 +239,5 @@ def print_value(value, percent_base=0):
|
|||||||
locale.format("%.1f", value * percent_base),
|
locale.format("%.1f", value * percent_base),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
verbose_value = "%s" % value
|
verbose_value = value
|
||||||
return verbose_value
|
return verbose_value
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
from django.utils.translation import ugettext as _
|
|
||||||
|
|
||||||
from ..utils.rest_api import ValidationError
|
from ..utils.rest_api import ValidationError
|
||||||
|
|
||||||
|
|
||||||
@ -16,6 +14,6 @@ def default_votes_validator(data):
|
|||||||
and data[key] < -2
|
and data[key] < -2
|
||||||
):
|
):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("Value for {} must not be less than -2").format(key)}
|
{"detail": f"Value for {key} must not be less than -2"}
|
||||||
)
|
)
|
||||||
return data
|
return data
|
||||||
|
@ -100,7 +100,7 @@ class UserManager(BaseUserManager):
|
|||||||
counter = 0
|
counter = 0
|
||||||
while True:
|
while True:
|
||||||
counter += 1
|
counter += 1
|
||||||
test_name = "%s %d" % (base_name, counter)
|
test_name = f"{base_name} {counter}"
|
||||||
if not self.filter(username=test_name).exists():
|
if not self.filter(username=test_name).exists():
|
||||||
generated_username = test_name
|
generated_username = test_name
|
||||||
break
|
break
|
||||||
@ -247,7 +247,7 @@ class User(RESTModelMixin, PermissionsMixin, AbstractBaseUser):
|
|||||||
helptext = " Is the email sender correct?"
|
helptext = " Is the email sender correct?"
|
||||||
connection.close()
|
connection.close()
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": "Error {}. Cannot send email.{}".format(error, helptext)}
|
{"detail": f"Error {error}. Cannot send email.{helptext}"}
|
||||||
)
|
)
|
||||||
except smtplib.SMTPRecipientsRefused:
|
except smtplib.SMTPRecipientsRefused:
|
||||||
pass # Run into returning false later
|
pass # Run into returning false later
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
from django.contrib.auth.hashers import make_password
|
from django.contrib.auth.hashers import make_password
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
|
||||||
|
|
||||||
from ..utils.autoupdate import inform_changed_data
|
from ..utils.autoupdate import inform_changed_data
|
||||||
from ..utils.rest_api import (
|
from ..utils.rest_api import (
|
||||||
@ -47,7 +46,7 @@ class UserFullSerializer(ModelSerializer):
|
|||||||
many=True,
|
many=True,
|
||||||
required=False,
|
required=False,
|
||||||
queryset=Group.objects.exclude(pk=1),
|
queryset=Group.objects.exclude(pk=1),
|
||||||
help_text=ugettext_lazy(
|
help_text=(
|
||||||
"The groups this user belongs to. A user will "
|
"The groups this user belongs to. A user will "
|
||||||
"get all permissions granted to each of "
|
"get all permissions granted to each of "
|
||||||
"his/her groups."
|
"his/her groups."
|
||||||
@ -79,11 +78,7 @@ class UserFullSerializer(ModelSerializer):
|
|||||||
data.get("username") or data.get("first_name") or data.get("last_name")
|
data.get("username") or data.get("first_name") or data.get("last_name")
|
||||||
):
|
):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{"detail": "Username, given name and surname can not all be empty."}
|
||||||
"detail": _(
|
|
||||||
"Username, given name and surname can not all be empty."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Generate username. But only if it is not set and the serializer is not
|
# Generate username. But only if it is not set and the serializer is not
|
||||||
@ -122,12 +117,8 @@ class PermissionRelatedField(RelatedField):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
"incorrect_value": ugettext_lazy(
|
"incorrect_value": 'Incorrect value "{value}". Expected app_label.codename string.',
|
||||||
'Incorrect value "{value}". Expected app_label.codename string.'
|
"does_not_exist": 'Invalid permission "{value}". Object does not exist.',
|
||||||
),
|
|
||||||
"does_not_exist": ugettext_lazy(
|
|
||||||
'Invalid permission "{value}". Object does not exist.'
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def to_representation(self, value):
|
def to_representation(self, value):
|
||||||
|
@ -18,7 +18,6 @@ from django.core.exceptions import ValidationError as DjangoValidationError
|
|||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.utils.encoding import force_bytes, force_text
|
from django.utils.encoding import force_bytes, force_text
|
||||||
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
|
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
|
|
||||||
from ..core.config import config
|
from ..core.config import config
|
||||||
from ..core.signals import permission_change
|
from ..core.signals import permission_change
|
||||||
@ -108,7 +107,7 @@ class UserViewSet(ModelViewSet):
|
|||||||
# The user has all permissions so he may update every user.
|
# The user has all permissions so he may update every user.
|
||||||
if request.data.get("is_active") is False and user == request.user:
|
if request.data.get("is_active") is False and user == request.user:
|
||||||
# But a user can not deactivate himself.
|
# But a user can not deactivate himself.
|
||||||
raise ValidationError({"detail": _("You can not deactivate yourself.")})
|
raise ValidationError({"detail": "You can not deactivate yourself."})
|
||||||
else:
|
else:
|
||||||
# The user does not have all permissions so he may only update himself.
|
# The user does not have all permissions so he may only update himself.
|
||||||
if str(request.user.pk) != self.kwargs["pk"]:
|
if str(request.user.pk) != self.kwargs["pk"]:
|
||||||
@ -134,7 +133,7 @@ class UserViewSet(ModelViewSet):
|
|||||||
"""
|
"""
|
||||||
instance = self.get_object()
|
instance = self.get_object()
|
||||||
if instance == self.request.user:
|
if instance == self.request.user:
|
||||||
raise ValidationError({"detail": _("You can not delete yourself.")})
|
raise ValidationError({"detail": "You can not delete yourself."})
|
||||||
self.perform_destroy(instance)
|
self.perform_destroy(instance)
|
||||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
@ -151,8 +150,8 @@ class UserViewSet(ModelViewSet):
|
|||||||
raise ValidationError({"detail": " ".join(errors)})
|
raise ValidationError({"detail": " ".join(errors)})
|
||||||
user.set_password(request.data.get("password"))
|
user.set_password(request.data.get("password"))
|
||||||
user.save()
|
user.save()
|
||||||
return Response({"detail": _("Password successfully reset.")})
|
return Response({"detail": "Password successfully reset."})
|
||||||
else:
|
|
||||||
raise ValidationError({"detail": "Password has to be a string."})
|
raise ValidationError({"detail": "Password has to be a string."})
|
||||||
|
|
||||||
@list_route(methods=["post"])
|
@list_route(methods=["post"])
|
||||||
@ -193,9 +192,7 @@ class UserViewSet(ModelViewSet):
|
|||||||
inform_changed_data(created_users)
|
inform_changed_data(created_users)
|
||||||
return Response(
|
return Response(
|
||||||
{
|
{
|
||||||
"detail": _("{number} users successfully imported.").format(
|
"detail": f"{len(created_users)} users successfully imported.",
|
||||||
number=len(created_users)
|
|
||||||
),
|
|
||||||
"importedTrackIds": imported_track_ids,
|
"importedTrackIds": imported_track_ids,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -230,13 +227,11 @@ class UserViewSet(ModelViewSet):
|
|||||||
except ConnectionRefusedError:
|
except ConnectionRefusedError:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{
|
{
|
||||||
"detail": "Cannot connect to SMTP server on {}:{}".format(
|
"detail": f"Cannot connect to SMTP server on {settings.EMAIL_HOST}:{settings.EMAIL_PORT}"
|
||||||
settings.EMAIL_HOST, settings.EMAIL_PORT
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
except smtplib.SMTPException as e:
|
except smtplib.SMTPException as err:
|
||||||
raise ValidationError({"detail": "{}: {}".format(e.errno, e.strerror)})
|
raise ValidationError({"detail": f"{err.errno}: {err.strerror}"})
|
||||||
|
|
||||||
success_users = []
|
success_users = []
|
||||||
user_pks_without_email = []
|
user_pks_without_email = []
|
||||||
@ -249,8 +244,8 @@ class UserViewSet(ModelViewSet):
|
|||||||
success_users.append(user)
|
success_users.append(user)
|
||||||
else:
|
else:
|
||||||
user_pks_without_email.append(user.pk)
|
user_pks_without_email.append(user.pk)
|
||||||
except DjangoValidationError as e:
|
except DjangoValidationError as err:
|
||||||
raise ValidationError(e.message_dict)
|
raise ValidationError(err.message_dict)
|
||||||
|
|
||||||
connection.close()
|
connection.close()
|
||||||
inform_changed_data(success_users)
|
inform_changed_data(success_users)
|
||||||
@ -358,13 +353,13 @@ class GroupViewSet(ModelViewSet):
|
|||||||
new_permissions = diff(given_permissions, old_permissions)
|
new_permissions = diff(given_permissions, old_permissions)
|
||||||
|
|
||||||
# Some permissions are added.
|
# Some permissions are added.
|
||||||
if len(new_permissions) > 0:
|
if new_permissions:
|
||||||
elements: List[Element] = []
|
elements: List[Element] = []
|
||||||
signal_results = permission_change.send(
|
signal_results = permission_change.send(
|
||||||
None, permissions=new_permissions, action="added"
|
None, permissions=new_permissions, action="added"
|
||||||
)
|
)
|
||||||
all_full_data = async_to_sync(element_cache.get_all_full_data)()
|
all_full_data = async_to_sync(element_cache.get_all_full_data)()
|
||||||
for receiver, signal_collections in signal_results:
|
for __, signal_collections in signal_results:
|
||||||
for cachable in signal_collections:
|
for cachable in signal_collections:
|
||||||
for full_data in all_full_data.get(
|
for full_data in all_full_data.get(
|
||||||
cachable.get_collection_string(), {}
|
cachable.get_collection_string(), {}
|
||||||
@ -476,11 +471,11 @@ class UserLoginView(APIView):
|
|||||||
# If the client tells that cookies are disabled, do not continue as guest (if enabled)
|
# If the client tells that cookies are disabled, do not continue as guest (if enabled)
|
||||||
if not self.request.data.get("cookies", True):
|
if not self.request.data.get("cookies", True):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("Cookies have to be enabled to use OpenSlides.")}
|
{"detail": "Cookies have to be enabled to use OpenSlides."}
|
||||||
)
|
)
|
||||||
form = AuthenticationForm(self.request, data=self.request.data)
|
form = AuthenticationForm(self.request, data=self.request.data)
|
||||||
if not form.is_valid():
|
if not form.is_valid():
|
||||||
raise ValidationError({"detail": _("Username or password is not correct.")})
|
raise ValidationError({"detail": "Username or password is not correct."})
|
||||||
self.user = form.get_user()
|
self.user = form.get_user()
|
||||||
auth_login(self.request, self.user)
|
auth_login(self.request, self.user)
|
||||||
return super().post(*args, **kwargs)
|
return super().post(*args, **kwargs)
|
||||||
@ -505,13 +500,10 @@ class UserLoginView(APIView):
|
|||||||
context["info_text"] = ""
|
context["info_text"] = ""
|
||||||
else:
|
else:
|
||||||
if user.check_password("admin"):
|
if user.check_password("admin"):
|
||||||
context["info_text"] = _(
|
context["info_text"] = (
|
||||||
"Installation was successfully. Use {username} and "
|
f"Installation was successfully. Use <strong>admin</strong> and "
|
||||||
"{password} for first login. Important: Please change "
|
"<strong>admin</strong> for first login. Important: Please change "
|
||||||
"your password!"
|
"your password!"
|
||||||
).format(
|
|
||||||
username="<strong>admin</strong>",
|
|
||||||
password="<strong>admin</strong>",
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
context["info_text"] = ""
|
context["info_text"] = ""
|
||||||
@ -537,7 +529,7 @@ class UserLogoutView(APIView):
|
|||||||
|
|
||||||
def post(self, *args, **kwargs):
|
def post(self, *args, **kwargs):
|
||||||
if not self.request.user.is_authenticated:
|
if not self.request.user.is_authenticated:
|
||||||
raise ValidationError({"detail": _("You are not authenticated.")})
|
raise ValidationError({"detail": "You are not authenticated."})
|
||||||
auth_logout(self.request)
|
auth_logout(self.request)
|
||||||
return super().post(*args, **kwargs)
|
return super().post(*args, **kwargs)
|
||||||
|
|
||||||
@ -588,7 +580,7 @@ class SetPasswordView(APIView):
|
|||||||
user.save()
|
user.save()
|
||||||
update_session_auth_hash(request, user)
|
update_session_auth_hash(request, user)
|
||||||
else:
|
else:
|
||||||
raise ValidationError({"detail": _("Old password does not match.")})
|
raise ValidationError({"detail": "Old password does not match."})
|
||||||
return super().post(request, *args, **kwargs)
|
return super().post(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@ -623,7 +615,7 @@ class PasswordResetView(APIView):
|
|||||||
"username": user.get_username(),
|
"username": user.get_username(),
|
||||||
}
|
}
|
||||||
# Send a django.core.mail.EmailMessage to `to_email`.
|
# Send a django.core.mail.EmailMessage to `to_email`.
|
||||||
subject = _("Password reset for {}").format(site_name)
|
subject = f"Password reset for {site_name}"
|
||||||
subject = "".join(subject.splitlines())
|
subject = "".join(subject.splitlines())
|
||||||
body = self.get_email_body(**context)
|
body = self.get_email_body(**context)
|
||||||
from_email = None # TODO: Add nice from_email here.
|
from_email = None # TODO: Add nice from_email here.
|
||||||
@ -680,13 +672,13 @@ class PasswordResetConfirmView(APIView):
|
|||||||
password = request.data.get("password")
|
password = request.data.get("password")
|
||||||
if not (uidb64 and token and password):
|
if not (uidb64 and token and password):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": _("You have to provide user_id, token and password.")}
|
{"detail": "You have to provide user_id, token and password."}
|
||||||
)
|
)
|
||||||
user = self.get_user(uidb64)
|
user = self.get_user(uidb64)
|
||||||
if user is None:
|
if user is None:
|
||||||
raise ValidationError({"detail": _("User does not exist.")})
|
raise ValidationError({"detail": "User does not exist."})
|
||||||
if not default_token_generator.check_token(user, token):
|
if not default_token_generator.check_token(user, token):
|
||||||
raise ValidationError({"detail": _("Invalid token.")})
|
raise ValidationError({"detail": "Invalid token."})
|
||||||
try:
|
try:
|
||||||
validate_password(password, user=user)
|
validate_password(password, user=user)
|
||||||
except DjangoValidationError as errors:
|
except DjangoValidationError as errors:
|
||||||
|
@ -9,7 +9,7 @@ class OpenSlidesArguments:
|
|||||||
if not self.args:
|
if not self.args:
|
||||||
raise KeyError("Arguments are not set.")
|
raise KeyError("Arguments are not set.")
|
||||||
if not hasattr(self.args, key):
|
if not hasattr(self.args, key):
|
||||||
raise KeyError("Key '{}' is not in the OpenSlides arguments.".format(key))
|
raise KeyError(f"Key '{key}' is not in the OpenSlides arguments.")
|
||||||
return getattr(self.args, key)
|
return getattr(self.args, key)
|
||||||
|
|
||||||
def get(self, key: str, default: Any) -> Any:
|
def get(self, key: str, default: Any) -> Any:
|
||||||
|
@ -31,8 +31,7 @@ def get_group_model() -> Model:
|
|||||||
)
|
)
|
||||||
except LookupError:
|
except LookupError:
|
||||||
raise ImproperlyConfigured(
|
raise ImproperlyConfigured(
|
||||||
"AUTH_GROUP_MODEL refers to model '%s' that has not been installed"
|
f"AUTH_GROUP_MODEL refers to model '{settings.AUTH_GROUP_MODEL}' that has not been installed"
|
||||||
% settings.AUTH_GROUP_MODEL
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -69,7 +68,7 @@ async def async_has_perm(user_id: int, perm: str) -> bool:
|
|||||||
user_collection_string, user_id
|
user_collection_string, user_id
|
||||||
)
|
)
|
||||||
if user_data is None:
|
if user_data is None:
|
||||||
raise RuntimeError("User with id {} does not exist.".format(user_id))
|
raise RuntimeError(f"User with id {user_id} does not exist.")
|
||||||
if GROUP_ADMIN_PK in user_data["groups_id"]:
|
if GROUP_ADMIN_PK in user_data["groups_id"]:
|
||||||
# User in admin group (pk 2) grants all permissions.
|
# User in admin group (pk 2) grants all permissions.
|
||||||
has_perm = True
|
has_perm = True
|
||||||
@ -83,7 +82,7 @@ async def async_has_perm(user_id: int, perm: str) -> bool:
|
|||||||
)
|
)
|
||||||
if group is None:
|
if group is None:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"User is in non existing group with id {}.".format(group_id)
|
f"User is in non existing group with id {group_id}."
|
||||||
)
|
)
|
||||||
|
|
||||||
if perm in group["permissions"]:
|
if perm in group["permissions"]:
|
||||||
@ -134,7 +133,7 @@ async def async_in_some_groups(user_id: int, groups: List[int]) -> bool:
|
|||||||
user_collection_string, user_id
|
user_collection_string, user_id
|
||||||
)
|
)
|
||||||
if user_data is None:
|
if user_data is None:
|
||||||
raise RuntimeError("User with id {} does not exist.".format(user_id))
|
raise RuntimeError(f"User with id {user_id} does not exist.")
|
||||||
if GROUP_ADMIN_PK in user_data["groups_id"]:
|
if GROUP_ADMIN_PK in user_data["groups_id"]:
|
||||||
# User in admin group (pk 2) grants all permissions.
|
# User in admin group (pk 2) grants all permissions.
|
||||||
in_some_groups = True
|
in_some_groups = True
|
||||||
@ -205,6 +204,6 @@ def user_to_user_id(user: AnyUser) -> int:
|
|||||||
user_id = user.pk
|
user_id = user.pk
|
||||||
else:
|
else:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
"Unsupported type for user. User {} has type {}.".format(user, type(user))
|
f"Unsupported type for user. User {user} has type {type(user)}."
|
||||||
)
|
)
|
||||||
return user_id
|
return user_id
|
||||||
|
@ -207,10 +207,8 @@ class ElementCache:
|
|||||||
# When change_id is lower then the lowest change_id in redis, we can
|
# When change_id is lower then the lowest change_id in redis, we can
|
||||||
# not inform the user about deleted elements.
|
# not inform the user about deleted elements.
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"change_id {} is lower then the lowest change_id in redis {}. "
|
f"change_id {change_id} is lower then the lowest change_id in redis {lowest_change_id}. "
|
||||||
"Catch this exception and rerun the method with change_id=0.".format(
|
"Catch this exception and rerun the method with change_id=0."
|
||||||
change_id, lowest_change_id
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
raw_changed_elements, deleted_elements = await self.cache_provider.get_data_since(
|
raw_changed_elements, deleted_elements = await self.cache_provider.get_data_since(
|
||||||
@ -270,7 +268,7 @@ class ElementCache:
|
|||||||
# Try to write a special key.
|
# Try to write a special key.
|
||||||
# If this succeeds, there is noone else currently updating the cache.
|
# If this succeeds, there is noone else currently updating the cache.
|
||||||
# TODO: Make a timeout. Else this could block forever
|
# TODO: Make a timeout. Else this could block forever
|
||||||
lock_name = "restricted_data_{}".format(user_id)
|
lock_name = f"restricted_data_{user_id}"
|
||||||
if await self.cache_provider.set_lock(lock_name):
|
if await self.cache_provider.set_lock(lock_name):
|
||||||
future: asyncio.Future = asyncio.Future()
|
future: asyncio.Future = asyncio.Future()
|
||||||
self.restricted_data_cache_updater[user_id] = future
|
self.restricted_data_cache_updater[user_id] = future
|
||||||
@ -375,10 +373,8 @@ class ElementCache:
|
|||||||
# When change_id is lower then the lowest change_id in redis, we can
|
# When change_id is lower then the lowest change_id in redis, we can
|
||||||
# not inform the user about deleted elements.
|
# not inform the user about deleted elements.
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"change_id {} is lower then the lowest change_id in redis {}. "
|
f"change_id {change_id} is lower then the lowest change_id in redis {lowest_change_id}. "
|
||||||
"Catch this exception and rerun the method with change_id=0.".format(
|
"Catch this exception and rerun the method with change_id=0."
|
||||||
change_id, lowest_change_id
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# If another coroutine or another daphne server also updates the restricted
|
# If another coroutine or another daphne server also updates the restricted
|
||||||
|
@ -108,7 +108,7 @@ class RedisCacheProvider:
|
|||||||
await redis.eval(
|
await redis.eval(
|
||||||
"return redis.call('del', 'fake_key', unpack(redis.call('keys', ARGV[1])))",
|
"return redis.call('del', 'fake_key', unpack(redis.call('keys', ARGV[1])))",
|
||||||
keys=[],
|
keys=[],
|
||||||
args=["{}*".format(self.prefix)],
|
args=[f"{self.prefix}*"],
|
||||||
)
|
)
|
||||||
|
|
||||||
async def reset_full_cache(self, data: Dict[str, str]) -> None:
|
async def reset_full_cache(self, data: Dict[str, str]) -> None:
|
||||||
@ -123,7 +123,7 @@ class RedisCacheProvider:
|
|||||||
tr.eval(
|
tr.eval(
|
||||||
"return redis.call('del', 'fake_key', unpack(redis.call('keys', ARGV[1])))",
|
"return redis.call('del', 'fake_key', unpack(redis.call('keys', ARGV[1])))",
|
||||||
keys=[],
|
keys=[],
|
||||||
args=["{}{}*".format(self.prefix, self.restricted_user_cache_key)],
|
args=[f"{self.prefix}{self.restricted_user_cache_key}*"],
|
||||||
)
|
)
|
||||||
tr.delete(self.get_change_id_cache_key())
|
tr.delete(self.get_change_id_cache_key())
|
||||||
tr.delete(self.get_full_data_cache_key())
|
tr.delete(self.get_full_data_cache_key())
|
||||||
@ -296,14 +296,14 @@ class RedisCacheProvider:
|
|||||||
"""
|
"""
|
||||||
# TODO: Improve lock. See: https://redis.io/topics/distlock
|
# TODO: Improve lock. See: https://redis.io/topics/distlock
|
||||||
async with get_connection() as redis:
|
async with get_connection() as redis:
|
||||||
return await redis.setnx("{}lock_{}".format(self.prefix, lock_name), 1)
|
return await redis.setnx(f"{self.prefix}lock_{lock_name}", 1)
|
||||||
|
|
||||||
async def get_lock(self, lock_name: str) -> bool:
|
async def get_lock(self, lock_name: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Returns True, when the lock for the restricted_data of an user is set. Else False.
|
Returns True, when the lock for the restricted_data of an user is set. Else False.
|
||||||
"""
|
"""
|
||||||
async with get_connection() as redis:
|
async with get_connection() as redis:
|
||||||
return await redis.get("{}lock_{}".format(self.prefix, lock_name))
|
return await redis.get(f"{self.prefix}lock_{lock_name}")
|
||||||
|
|
||||||
async def del_lock(self, lock_name: str) -> None:
|
async def del_lock(self, lock_name: str) -> None:
|
||||||
"""
|
"""
|
||||||
@ -311,7 +311,7 @@ class RedisCacheProvider:
|
|||||||
lock is not set.
|
lock is not set.
|
||||||
"""
|
"""
|
||||||
async with get_connection() as redis:
|
async with get_connection() as redis:
|
||||||
await redis.delete("{}lock_{}".format(self.prefix, lock_name))
|
await redis.delete(f"{self.prefix}lock_{lock_name}")
|
||||||
|
|
||||||
async def get_change_id_user(self, user_id: int) -> Optional[int]:
|
async def get_change_id_user(self, user_id: int) -> Optional[int]:
|
||||||
"""
|
"""
|
||||||
|
@ -123,7 +123,7 @@ class SiteConsumer(ProtocollAsyncJsonWebsocketConsumer):
|
|||||||
projector_data: Dict[int, Dict[str, Any]] = {}
|
projector_data: Dict[int, Dict[str, Any]] = {}
|
||||||
for projector_id in self.listen_projector_ids:
|
for projector_id in self.listen_projector_ids:
|
||||||
data = all_projector_data.get(
|
data = all_projector_data.get(
|
||||||
projector_id, {"error": "No data for projector {}".format(projector_id)}
|
projector_id, {"error": f"No data for projector {projector_id}"}
|
||||||
)
|
)
|
||||||
new_hash = hash(str(data))
|
new_hash = hash(str(data))
|
||||||
if new_hash != self.projector_hash[projector_id]:
|
if new_hash != self.projector_hash[projector_id]:
|
||||||
|
@ -80,7 +80,7 @@ def get_default_settings_dir(openslides_type: str = None) -> str:
|
|||||||
elif openslides_type == WINDOWS_PORTABLE_VERSION:
|
elif openslides_type == WINDOWS_PORTABLE_VERSION:
|
||||||
parent_directory = get_win32_portable_dir()
|
parent_directory = get_win32_portable_dir()
|
||||||
else:
|
else:
|
||||||
raise TypeError("%s is not a valid OpenSlides type." % openslides_type)
|
raise TypeError(f"{openslides_type} is not a valid OpenSlides type.")
|
||||||
return os.path.join(parent_directory, "openslides")
|
return os.path.join(parent_directory, "openslides")
|
||||||
|
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ def get_default_user_data_dir(openslides_type: str) -> str:
|
|||||||
elif openslides_type == WINDOWS_PORTABLE_VERSION:
|
elif openslides_type == WINDOWS_PORTABLE_VERSION:
|
||||||
default_user_data_dir = get_win32_portable_dir()
|
default_user_data_dir = get_win32_portable_dir()
|
||||||
else:
|
else:
|
||||||
raise TypeError("%s is not a valid OpenSlides type." % openslides_type)
|
raise TypeError(f"{openslides_type} is not a valid OpenSlides type.")
|
||||||
return default_user_data_dir
|
return default_user_data_dir
|
||||||
|
|
||||||
|
|
||||||
@ -298,9 +298,9 @@ def open_browser(host: str, port: int) -> None:
|
|||||||
"""
|
"""
|
||||||
if host == "0.0.0.0":
|
if host == "0.0.0.0":
|
||||||
# Windows does not support 0.0.0.0, so use 'localhost' instead
|
# Windows does not support 0.0.0.0, so use 'localhost' instead
|
||||||
start_browser("http://localhost:%s" % port)
|
start_browser(f"http://localhost:{port}")
|
||||||
else:
|
else:
|
||||||
start_browser("http://%s:%s" % (host, port))
|
start_browser(f"http://{host}:{port}")
|
||||||
|
|
||||||
|
|
||||||
def start_browser(browser_url: str) -> None:
|
def start_browser(browser_url: str) -> None:
|
||||||
|
@ -39,7 +39,7 @@ def get_element_id(collection_string: str, id: int) -> str:
|
|||||||
"""
|
"""
|
||||||
Returns a combined string from the collection_string and an id.
|
Returns a combined string from the collection_string and an id.
|
||||||
"""
|
"""
|
||||||
return "{}:{}".format(collection_string, id)
|
return f"{collection_string}:{id}"
|
||||||
|
|
||||||
|
|
||||||
def split_element_id(element_id: Union[str, bytes]) -> Tuple[str, int]:
|
def split_element_id(element_id: Union[str, bytes]) -> Tuple[str, int]:
|
||||||
@ -92,8 +92,6 @@ def get_model_from_collection_string(collection_string: str) -> Type[Model]:
|
|||||||
model = _models_to_collection_string[collection_string]
|
model = _models_to_collection_string[collection_string]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Invalid message. A valid collection_string is missing. Got {}".format(
|
f"Invalid message. A valid collection_string is missing. Got {collection_string}"
|
||||||
collection_string
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
return model
|
return model
|
||||||
|
@ -92,32 +92,28 @@ class Command(BaseCommand):
|
|||||||
"-t",
|
"-t",
|
||||||
"--topics",
|
"--topics",
|
||||||
type=int,
|
type=int,
|
||||||
help="Number of topics to be created (default {}).".format(DEFAULT_NUMBER),
|
help=f"Number of topics to be created (default {DEFAULT_NUMBER}).",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-m",
|
"-m",
|
||||||
"--motions",
|
"--motions",
|
||||||
type=int,
|
type=int,
|
||||||
help="Number of motions to be created (default {}).".format(DEFAULT_NUMBER),
|
help=f"Number of motions to be created (default {DEFAULT_NUMBER}).",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-a",
|
"-a",
|
||||||
"--assignments",
|
"--assignments",
|
||||||
type=int,
|
type=int,
|
||||||
help="Number of assignments to be created (default {}).".format(
|
help=f"Number of assignments to be created (default {DEFAULT_NUMBER}).",
|
||||||
DEFAULT_NUMBER
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-u",
|
"-u",
|
||||||
"--users",
|
"--users",
|
||||||
nargs=2,
|
nargs=2,
|
||||||
type=int,
|
type=int,
|
||||||
help="Number of users to be created. The first number of users is "
|
help=f"Number of users to be created. The first number of users is "
|
||||||
'added to the group "Staff" (default {}). The second number '
|
'added to the group "Staff" (default {DEFAULT_NUMBER}). The second number '
|
||||||
"of users is not added to any group (default {}).".format(
|
"of users is not added to any group (default {DEFAULT_NUMBER}).",
|
||||||
DEFAULT_NUMBER, DEFAULT_NUMBER
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
@ -132,7 +128,7 @@ class Command(BaseCommand):
|
|||||||
if number_of_topics is None and not options["only"]:
|
if number_of_topics is None and not options["only"]:
|
||||||
number_of_topics = DEFAULT_NUMBER
|
number_of_topics = DEFAULT_NUMBER
|
||||||
if number_of_topics is not None and number_of_topics > 0:
|
if number_of_topics is not None and number_of_topics > 0:
|
||||||
self.stdout.write("Start creating {} topcis ...".format(number_of_topics))
|
self.stdout.write(f"Start creating {number_of_topics} topcis ...")
|
||||||
current_topics = list(Topic.objects.values_list("id", flat=True))
|
current_topics = list(Topic.objects.values_list("id", flat=True))
|
||||||
new_topics = []
|
new_topics = []
|
||||||
for i in range(number_of_topics):
|
for i in range(number_of_topics):
|
||||||
@ -143,9 +139,7 @@ class Command(BaseCommand):
|
|||||||
items.append(Item(content_object=topic, type=Item.AGENDA_ITEM))
|
items.append(Item(content_object=topic, type=Item.AGENDA_ITEM))
|
||||||
Item.objects.bulk_create(items)
|
Item.objects.bulk_create(items)
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
self.style.SUCCESS(
|
self.style.SUCCESS(f"{number_of_topics} topcis successfully created.")
|
||||||
"{} topcis successfully created.".format(number_of_topics)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
elif number_of_topics is not None and number_of_topics < 0:
|
elif number_of_topics is not None and number_of_topics < 0:
|
||||||
raise CommandError("Number for topics must not be negative.")
|
raise CommandError("Number for topics must not be negative.")
|
||||||
@ -156,7 +150,7 @@ class Command(BaseCommand):
|
|||||||
if number_of_motions is None and not options["only"]:
|
if number_of_motions is None and not options["only"]:
|
||||||
number_of_motions = DEFAULT_NUMBER
|
number_of_motions = DEFAULT_NUMBER
|
||||||
if number_of_motions is not None and number_of_motions > 0:
|
if number_of_motions is not None and number_of_motions > 0:
|
||||||
self.stdout.write("Start creating {} motions ...".format(number_of_motions))
|
self.stdout.write(f"Start creating {number_of_motions} motions ...")
|
||||||
text = ""
|
text = ""
|
||||||
for i in range(MOTION_NUMBER_OF_PARAGRAPHS):
|
for i in range(MOTION_NUMBER_OF_PARAGRAPHS):
|
||||||
text += dedent(LOREM_IPSUM[i % 3])
|
text += dedent(LOREM_IPSUM[i % 3])
|
||||||
@ -164,9 +158,7 @@ class Command(BaseCommand):
|
|||||||
motion = Motion(title=get_random_string(20, self.chars), text=text)
|
motion = Motion(title=get_random_string(20, self.chars), text=text)
|
||||||
motion.save(skip_autoupdate=True)
|
motion.save(skip_autoupdate=True)
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
self.style.SUCCESS(
|
self.style.SUCCESS(f"{number_of_motions} motions successfully created.")
|
||||||
"{} motions successfully created.".format(number_of_motions)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
elif number_of_motions is not None and number_of_motions < 0:
|
elif number_of_motions is not None and number_of_motions < 0:
|
||||||
raise CommandError("Number for motions must not be negative.")
|
raise CommandError("Number for motions must not be negative.")
|
||||||
@ -177,9 +169,7 @@ class Command(BaseCommand):
|
|||||||
if number_of_assignments is None and not options["only"]:
|
if number_of_assignments is None and not options["only"]:
|
||||||
number_of_assignments = DEFAULT_NUMBER
|
number_of_assignments = DEFAULT_NUMBER
|
||||||
if number_of_assignments is not None and number_of_assignments > 0:
|
if number_of_assignments is not None and number_of_assignments > 0:
|
||||||
self.stdout.write(
|
self.stdout.write(f"Start creating {number_of_assignments} assignments ...")
|
||||||
"Start creating {} assignments ...".format(number_of_assignments)
|
|
||||||
)
|
|
||||||
current_assignments = list(Assignment.objects.values_list("id", flat=True))
|
current_assignments = list(Assignment.objects.values_list("id", flat=True))
|
||||||
new_assignments = []
|
new_assignments = []
|
||||||
for i in range(number_of_assignments):
|
for i in range(number_of_assignments):
|
||||||
@ -193,7 +183,7 @@ class Command(BaseCommand):
|
|||||||
Item.objects.bulk_create(items)
|
Item.objects.bulk_create(items)
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
self.style.SUCCESS(
|
self.style.SUCCESS(
|
||||||
"{} assignments successfully created.".format(number_of_assignments)
|
f"{number_of_assignments} assignments successfully created."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif number_of_assignments is not None and number_of_assignments < 0:
|
elif number_of_assignments is not None and number_of_assignments < 0:
|
||||||
@ -212,7 +202,7 @@ class Command(BaseCommand):
|
|||||||
else:
|
else:
|
||||||
staff_users = options["users"][0]
|
staff_users = options["users"][0]
|
||||||
if staff_users is not None and staff_users > 0:
|
if staff_users is not None and staff_users > 0:
|
||||||
self.stdout.write("Start creating {} staff users ...".format(staff_users))
|
self.stdout.write(f"Start creating {staff_users} staff users ...")
|
||||||
group_staff = Group.objects.get(name="Staff")
|
group_staff = Group.objects.get(name="Staff")
|
||||||
hashed_password = make_password(PASSWORD)
|
hashed_password = make_password(PASSWORD)
|
||||||
current_users = list(User.objects.values_list("id", flat=True))
|
current_users = list(User.objects.values_list("id", flat=True))
|
||||||
@ -236,7 +226,7 @@ class Command(BaseCommand):
|
|||||||
user.groups.add(group_staff)
|
user.groups.add(group_staff)
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
self.style.SUCCESS(
|
self.style.SUCCESS(
|
||||||
"{} staff users successfully created.".format(staff_users)
|
f"{staff_users} staff users successfully created."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif staff_users is not None and staff_users < 0:
|
elif staff_users is not None and staff_users < 0:
|
||||||
@ -251,9 +241,7 @@ class Command(BaseCommand):
|
|||||||
else:
|
else:
|
||||||
default_users = options["users"][1]
|
default_users = options["users"][1]
|
||||||
if default_users is not None and default_users > 0:
|
if default_users is not None and default_users > 0:
|
||||||
self.stdout.write(
|
self.stdout.write(f"Start creating {default_users} default users ...")
|
||||||
"Start creating {} default users ...".format(default_users)
|
|
||||||
)
|
|
||||||
hashed_password = make_password(PASSWORD)
|
hashed_password = make_password(PASSWORD)
|
||||||
new_users = []
|
new_users = []
|
||||||
for i in range(default_users):
|
for i in range(default_users):
|
||||||
@ -273,7 +261,7 @@ class Command(BaseCommand):
|
|||||||
else:
|
else:
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
self.style.SUCCESS(
|
self.style.SUCCESS(
|
||||||
"{} default users successfully created.".format(default_users)
|
f"{default_users} default users successfully created."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif default_users is not None and default_users < 0:
|
elif default_users is not None and default_users < 0:
|
||||||
|
@ -9,7 +9,7 @@ class TestItemManager(TestCase):
|
|||||||
Test that get_root_and_children needs only one db query.
|
Test that get_root_and_children needs only one db query.
|
||||||
"""
|
"""
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
Topic.objects.create(title="item{}".format(i))
|
Topic.objects.create(title=f"item{i}")
|
||||||
|
|
||||||
with self.assertNumQueries(1):
|
with self.assertNumQueries(1):
|
||||||
Item.objects.get_root_and_children()
|
Item.objects.get_root_and_children()
|
||||||
|
@ -2,7 +2,6 @@ import pytest
|
|||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import ugettext
|
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.test import APIClient
|
from rest_framework.test import APIClient
|
||||||
|
|
||||||
@ -117,7 +116,7 @@ def test_agenda_item_db_queries():
|
|||||||
TODO: The last three request are a bug.
|
TODO: The last three request are a bug.
|
||||||
"""
|
"""
|
||||||
for index in range(10):
|
for index in range(10):
|
||||||
Topic.objects.create(title="topic{}".format(index))
|
Topic.objects.create(title=f"topic{index}")
|
||||||
parent = Topic.objects.create(title="parent").agenda_item
|
parent = Topic.objects.create(title="parent").agenda_item
|
||||||
child = Topic.objects.create(title="child").agenda_item
|
child = Topic.objects.create(title="child").agenda_item
|
||||||
child.parent = parent
|
child.parent = parent
|
||||||
@ -236,20 +235,12 @@ class ManageSpeaker(TestCase):
|
|||||||
reverse("item-manage-speaker", args=[self.item.pk]), {"speaker": "1"}
|
reverse("item-manage-speaker", args=[self.item.pk]), {"speaker": "1"}
|
||||||
)
|
)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(
|
|
||||||
response.data.get("detail"),
|
|
||||||
ugettext("No speakers have been removed from the list of speakers."),
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_remove_someone_else_invalid_data(self):
|
def test_remove_someone_else_invalid_data(self):
|
||||||
response = self.client.delete(
|
response = self.client.delete(
|
||||||
reverse("item-manage-speaker", args=[self.item.pk]), {"speaker": "invalid"}
|
reverse("item-manage-speaker", args=[self.item.pk]), {"speaker": "invalid"}
|
||||||
)
|
)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(
|
|
||||||
response.data.get("detail"),
|
|
||||||
ugettext("No speakers have been removed from the list of speakers."),
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_remove_someone_else_non_admin(self):
|
def test_remove_someone_else_non_admin(self):
|
||||||
admin = get_user_model().objects.get(username="admin")
|
admin = get_user_model().objects.get(username="admin")
|
||||||
|
@ -26,7 +26,7 @@ def test_assignment_db_queries():
|
|||||||
TODO: The last request are a bug.
|
TODO: The last request are a bug.
|
||||||
"""
|
"""
|
||||||
for index in range(10):
|
for index in range(10):
|
||||||
Assignment.objects.create(title="assignment{}".format(index), open_posts=1)
|
Assignment.objects.create(title=f"assignment{index}", open_posts=1)
|
||||||
|
|
||||||
assert count_queries(Assignment.get_elements) == 15
|
assert count_queries(Assignment.get_elements) == 15
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ def test_projector_db_queries():
|
|||||||
* 1 request to get the list of the projector defaults.
|
* 1 request to get the list of the projector defaults.
|
||||||
"""
|
"""
|
||||||
for index in range(10):
|
for index in range(10):
|
||||||
Projector.objects.create(name="Projector{}".format(index))
|
Projector.objects.create(name=f"Projector{index}")
|
||||||
|
|
||||||
assert count_queries(Projector.get_elements) == 2
|
assert count_queries(Projector.get_elements) == 2
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ def test_tag_db_queries():
|
|||||||
* 1 requests to get the list of all tags.
|
* 1 requests to get the list of all tags.
|
||||||
"""
|
"""
|
||||||
for index in range(10):
|
for index in range(10):
|
||||||
Tag.objects.create(name="tag{}".format(index))
|
Tag.objects.create(name=f"tag{index}")
|
||||||
|
|
||||||
assert count_queries(Tag.get_elements) == 1
|
assert count_queries(Tag.get_elements) == 1
|
||||||
|
|
||||||
|
@ -114,14 +114,10 @@ def count_queries(func, *args, **kwargs) -> int:
|
|||||||
with context:
|
with context:
|
||||||
func(*args, **kwargs)
|
func(*args, **kwargs)
|
||||||
|
|
||||||
print(
|
queries = "\n".join(
|
||||||
"%d queries executed\nCaptured queries were:\n%s"
|
f"{i}. {query['sql']}"
|
||||||
% (
|
|
||||||
len(context),
|
|
||||||
"\n".join(
|
|
||||||
"%d. %s" % (i, query["sql"])
|
|
||||||
for i, query in enumerate(context.captured_queries, start=1)
|
for i, query in enumerate(context.captured_queries, start=1)
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
print(f"{len(context)} queries executed\nCaptured queries were:\n{queries}")
|
||||||
return len(context)
|
return len(context)
|
||||||
|
@ -14,8 +14,8 @@ def test_mediafiles_db_queries():
|
|||||||
"""
|
"""
|
||||||
for index in range(10):
|
for index in range(10):
|
||||||
Mediafile.objects.create(
|
Mediafile.objects.create(
|
||||||
title="some_file{}".format(index),
|
title=f"some_file{index}",
|
||||||
mediafile=SimpleUploadedFile("some_file{}".format(index), b"some content."),
|
mediafile=SimpleUploadedFile(f"some_file{index}", b"some content."),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert count_queries(Mediafile.get_elements) == 1
|
assert count_queries(Mediafile.get_elements) == 1
|
||||||
|
@ -56,7 +56,7 @@ def test_motion_db_queries():
|
|||||||
section2 = MotionCommentSection.objects.create(name="test_section")
|
section2 = MotionCommentSection.objects.create(name="test_section")
|
||||||
|
|
||||||
for index in range(10):
|
for index in range(10):
|
||||||
motion = Motion.objects.create(title="motion{}".format(index))
|
motion = Motion.objects.create(title=f"motion{index}")
|
||||||
|
|
||||||
MotionComment.objects.create(
|
MotionComment.objects.create(
|
||||||
comment="test_comment", motion=motion, section=section1
|
comment="test_comment", motion=motion, section=section1
|
||||||
@ -66,7 +66,7 @@ def test_motion_db_queries():
|
|||||||
)
|
)
|
||||||
|
|
||||||
get_user_model().objects.create_user(
|
get_user_model().objects.create_user(
|
||||||
username="user_{}".format(index), password="password"
|
username=f"user_{index}", password="password"
|
||||||
)
|
)
|
||||||
# TODO: Create some polls etc.
|
# TODO: Create some polls etc.
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ def test_category_db_queries():
|
|||||||
* 1 requests to get the list of all categories.
|
* 1 requests to get the list of all categories.
|
||||||
"""
|
"""
|
||||||
for index in range(10):
|
for index in range(10):
|
||||||
Category.objects.create(name="category{}".format(index))
|
Category.objects.create(name=f"category{index}")
|
||||||
|
|
||||||
assert count_queries(Category.get_elements) == 1
|
assert count_queries(Category.get_elements) == 1
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ def test_statute_paragraph_db_queries():
|
|||||||
"""
|
"""
|
||||||
for index in range(10):
|
for index in range(10):
|
||||||
StatuteParagraph.objects.create(
|
StatuteParagraph.objects.create(
|
||||||
title="statute_paragraph{}".format(index), text="text{}".format(index)
|
title=f"statute_paragraph{index}", text=f"text{index}"
|
||||||
)
|
)
|
||||||
|
|
||||||
assert count_queries(StatuteParagraph.get_elements) == 1
|
assert count_queries(StatuteParagraph.get_elements) == 1
|
||||||
@ -475,7 +475,7 @@ class RetrieveMotion(TestCase):
|
|||||||
self.motion.create_poll()
|
self.motion.create_poll()
|
||||||
for index in range(10):
|
for index in range(10):
|
||||||
get_user_model().objects.create_user(
|
get_user_model().objects.create_user(
|
||||||
username="user_{}".format(index), password="password"
|
username=f"user_{index}", password="password"
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_guest_state_with_required_permission_to_see(self):
|
def test_guest_state_with_required_permission_to_see(self):
|
||||||
@ -889,7 +889,7 @@ class ManageComments(TestCase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
response.data["detail"], "A comment section with id 42 does not exist"
|
response.data["detail"], "A comment section with id 42 does not exist."
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_create_comment(self):
|
def test_create_comment(self):
|
||||||
@ -1700,7 +1700,7 @@ class CreateMotionPoll(TestCase):
|
|||||||
for key in ("yes", "no", "abstain"):
|
for key in ("yes", "no", "abstain"):
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
response.data["polls"][1][key] is None,
|
response.data["polls"][1][key] is None,
|
||||||
'Vote value "{}" should be None.'.format(key),
|
f"Vote value '{key}' should be None.",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ def test_topic_item_db_queries():
|
|||||||
* 1 request to get the agenda item
|
* 1 request to get the agenda item
|
||||||
"""
|
"""
|
||||||
for index in range(10):
|
for index in range(10):
|
||||||
Topic.objects.create(title="topic-{}".format(index))
|
Topic.objects.create(title=f"topic-{index}")
|
||||||
|
|
||||||
assert count_queries(Topic.get_elements) == 3
|
assert count_queries(Topic.get_elements) == 3
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ def test_user_db_queries():
|
|||||||
* 1 requests to get the list of all groups.
|
* 1 requests to get the list of all groups.
|
||||||
"""
|
"""
|
||||||
for index in range(10):
|
for index in range(10):
|
||||||
User.objects.create(username="user{}".format(index))
|
User.objects.create(username=f"user{index}")
|
||||||
|
|
||||||
assert count_queries(User.get_elements) == 3
|
assert count_queries(User.get_elements) == 3
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ def test_group_db_queries():
|
|||||||
* 1 request to get the permissions
|
* 1 request to get the permissions
|
||||||
"""
|
"""
|
||||||
for index in range(10):
|
for index in range(10):
|
||||||
Group.objects.create(name="group{}".format(index))
|
Group.objects.create(name=f"group{index}")
|
||||||
|
|
||||||
assert count_queries(Group.get_elements) == 2
|
assert count_queries(Group.get_elements) == 2
|
||||||
|
|
||||||
|
@ -49,8 +49,8 @@ async def get_communicator():
|
|||||||
def get_communicator(query_string=""):
|
def get_communicator(query_string=""):
|
||||||
nonlocal communicator # use the outer communicator variable
|
nonlocal communicator # use the outer communicator variable
|
||||||
if query_string:
|
if query_string:
|
||||||
query_string = "?{}".format(query_string)
|
query_string = f"?{query_string}"
|
||||||
communicator = WebsocketCommunicator(application, "/ws/{}".format(query_string))
|
communicator = WebsocketCommunicator(application, f"/ws/{query_string}")
|
||||||
return communicator
|
return communicator
|
||||||
|
|
||||||
yield get_communicator
|
yield get_communicator
|
||||||
@ -211,7 +211,7 @@ async def test_with_user():
|
|||||||
session[BACKEND_SESSION_KEY] = "django.contrib.auth.backends.ModelBackend"
|
session[BACKEND_SESSION_KEY] = "django.contrib.auth.backends.ModelBackend"
|
||||||
session.save()
|
session.save()
|
||||||
scn = settings.SESSION_COOKIE_NAME
|
scn = settings.SESSION_COOKIE_NAME
|
||||||
cookies = (b"cookie", "{}={}".format(scn, session.session_key).encode())
|
cookies = (b"cookie", f"{scn}={session.session_key}".encode())
|
||||||
communicator = WebsocketCommunicator(application, "/ws/", headers=[cookies])
|
communicator = WebsocketCommunicator(application, "/ws/", headers=[cookies])
|
||||||
|
|
||||||
connected, __ = await communicator.connect()
|
connected, __ = await communicator.connect()
|
||||||
|
@ -15,7 +15,7 @@ def restrict_elements(elements: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
|||||||
if key == "id":
|
if key == "id":
|
||||||
restricted_element[key] = value
|
restricted_element[key] = value
|
||||||
else:
|
else:
|
||||||
restricted_element[key] = "restricted_{}".format(value)
|
restricted_element[key] = f"restricted_{value}"
|
||||||
out.append(restricted_element)
|
out.append(restricted_element)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user