Merge pull request #4106 from ostcar/python-3.6-f-strings

use f-string syntax for strings
This commit is contained in:
Oskar Hahn 2019-01-18 17:47:12 +01:00 committed by GitHub
commit d5b09b4513
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
65 changed files with 370 additions and 36294 deletions

View File

@ -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)))

View File

@ -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__":

View File

@ -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
) )

View File

@ -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"]:

View File

@ -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)
)
}
)

View File

@ -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):

View File

@ -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

View File

@ -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):

View File

@ -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

View File

@ -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(

View File

@ -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"]]
)
) )
) )

View File

@ -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:

View File

@ -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":

View File

@ -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:

View File

@ -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."}
) )

View File

@ -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

View File

@ -1,677 +0,0 @@
# Language file of OpenSlides used by Transifex:
# https://www.transifex.com/openslides/openslides/
# Copyright (C) 20112015 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."

View File

@ -1,673 +0,0 @@
# Language file of OpenSlides used by Transifex:
# https://www.transifex.com/openslides/openslides/
# Copyright (C) 20112015 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."

View File

@ -1,665 +0,0 @@
# Language file of OpenSlides used by Transifex:
# https://www.transifex.com/openslides/openslides/
# Copyright (C) 20112015 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 ""

View File

@ -1,673 +0,0 @@
# Language file of OpenSlides used by Transifex:
# https://www.transifex.com/openslides/openslides/
# Copyright (C) 20112015 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."

View File

@ -1,673 +0,0 @@
# Language file of OpenSlides used by Transifex:
# https://www.transifex.com/openslides/openslides/
# Copyright (C) 20112015 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."

View File

@ -1,672 +0,0 @@
# Language file of OpenSlides used by Transifex:
# https://www.transifex.com/openslides/openslides/
# Copyright (C) 20112015 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."

View File

@ -1,672 +0,0 @@
# Language file of OpenSlides used by Transifex:
# https://www.transifex.com/openslides/openslides/
# Copyright (C) 20112015 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 "Старый пароль не совпадает."

View File

@ -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"

View File

@ -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."
) )

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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:

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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]:
""" """

View File

@ -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]:

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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()

View File

@ -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")

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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.",
) )

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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