diff --git a/symposion/boxes/models.py b/symposion/boxes/models.py index 4eb2a019..3c13edd1 100644 --- a/symposion/boxes/models.py +++ b/symposion/boxes/models.py @@ -1,5 +1,6 @@ from django.db import models from django.contrib.auth.models import User +from django.utils.translation import ugettext_lazy as _ import reversion @@ -8,17 +9,17 @@ from markitup.fields import MarkupField class Box(models.Model): - label = models.CharField(max_length=100, db_index=True) + label = models.CharField(max_length=100, db_index=True, verbose_name=_("Label")) content = MarkupField(blank=True) - created_by = models.ForeignKey(User, related_name="boxes") - last_updated_by = models.ForeignKey(User, related_name="updated_boxes") + created_by = models.ForeignKey(User, related_name="boxes", verbose_name=_("Created by")) + last_updated_by = models.ForeignKey(User, related_name="updated_boxes", verbose_name=_("Last updated by")) def __unicode__(self): return self.label class Meta: - verbose_name_plural = "boxes" - + verbose_name = _("Box") + verbose_name_plural = _("Boxes") reversion.register(Box) diff --git a/symposion/cms/models.py b/symposion/cms/models.py index 25c1caea..a1955402 100644 --- a/symposion/cms/models.py +++ b/symposion/cms/models.py @@ -38,6 +38,10 @@ class Page(models.Model): def __unicode__(self): return self.title + class Meta: + verbose_name = _("page") + verbose_name_plural = _("pages") + @models.permalink def get_absolute_url(self): return ("cms_page", [self.path]) diff --git a/symposion/conference/apps.py b/symposion/conference/apps.py index d7759eeb..7a330359 100644 --- a/symposion/conference/apps.py +++ b/symposion/conference/apps.py @@ -1,7 +1,8 @@ from django.apps import AppConfig +from django.utils.translation import ugettext_lazy as _ class ConferenceConfig(AppConfig): name = "symposion.conference" label = "symposion_conference" - verbose_name = "Symposion Conference" + verbose_name = _("Symposion Conference") diff --git a/symposion/conference/models.py b/symposion/conference/models.py index 582035b5..44e09627 100644 --- a/symposion/conference/models.py +++ b/symposion/conference/models.py @@ -12,14 +12,14 @@ class Conference(models.Model): the full conference for a specific year, e.g. US PyCon 2012. """ - title = models.CharField(_("title"), max_length=100) + title = models.CharField(_("Title"), max_length=100) # when the conference runs - start_date = models.DateField(_("start date"), null=True, blank=True) - end_date = models.DateField(_("end date"), null=True, blank=True) + start_date = models.DateField(_("Start date"), null=True, blank=True) + end_date = models.DateField(_("End date"), null=True, blank=True) # timezone the conference is in - timezone = TimeZoneField(_("timezone"), blank=True) + timezone = TimeZoneField(_("Timezone"), blank=True) def __unicode__(self): return self.title @@ -49,14 +49,14 @@ class Section(models.Model): scheduling process. """ - conference = models.ForeignKey(Conference, verbose_name=_("conference")) + conference = models.ForeignKey(Conference, verbose_name=_("Conference")) - name = models.CharField(_("name"), max_length=100) - slug = models.SlugField() + name = models.CharField(_("Name"), max_length=100) + slug = models.SlugField(verbose_name=_("Slug")) # when the section runs - start_date = models.DateField(_("start date"), null=True, blank=True) - end_date = models.DateField(_("end date"), null=True, blank=True) + start_date = models.DateField(_("Start date"), null=True, blank=True) + end_date = models.DateField(_("End date"), null=True, blank=True) def __unicode__(self): return u"%s %s" % (self.conference, self.name) diff --git a/symposion/forms.py b/symposion/forms.py index 09fc5d4f..bdaf89ae 100644 --- a/symposion/forms.py +++ b/symposion/forms.py @@ -6,13 +6,14 @@ except ImportError: from django import forms import account.forms +from django.utils.translation import ugettext_lazy as _ class SignupForm(account.forms.SignupForm): - first_name = forms.CharField() - last_name = forms.CharField() - email_confirm = forms.EmailField(label="Confirm Email") + first_name = forms.CharField(label=_("First name")) + last_name = forms.CharField(label=_("Last name")) + email_confirm = forms.EmailField(label=_("Confirm Email")) def __init__(self, *args, **kwargs): super(SignupForm, self).__init__(*args, **kwargs) @@ -32,7 +33,7 @@ class SignupForm(account.forms.SignupForm): if email: if email != email_confirm: raise forms.ValidationError( - "Email address must match previously typed email address") + _("Email address must match previously typed email address")) return email_confirm diff --git a/symposion/proposals/actions.py b/symposion/proposals/actions.py index d059da81..1edb6528 100644 --- a/symposion/proposals/actions.py +++ b/symposion/proposals/actions.py @@ -1,10 +1,11 @@ import csv from django.http import HttpResponse +from django.utils.translation import ugettext_lazy as _ -def export_as_csv_action(description="Export selected objects as CSV file", - fields=None, exclude=None, header=True): +def export_as_csv_action(description=None, fields=None, exclude=None, + header=True): """ This function returns an export csv action 'fields' and 'exclude' work like in Django ModelForm @@ -31,5 +32,7 @@ def export_as_csv_action(description="Export selected objects as CSV file", writer.writerow( [unicode(getattr(obj, field)).encode("utf-8", "replace") for field in field_names]) return response + if description is None: + description = _("Export selected objects as CSV file") export_as_csv.short_description = description return export_as_csv diff --git a/symposion/proposals/apps.py b/symposion/proposals/apps.py index 9a317525..c35c024c 100644 --- a/symposion/proposals/apps.py +++ b/symposion/proposals/apps.py @@ -1,7 +1,8 @@ from django.apps import AppConfig +from django.utils.translation import ugettext_lazy as _ class ProposalsConfig(AppConfig): name = "symposion.proposals" label = "symposion_proposals" - verbose_name = "Symposion Proposals" + verbose_name = _("Symposion Proposals") diff --git a/symposion/proposals/forms.py b/symposion/proposals/forms.py index 91c7e004..fada20be 100644 --- a/symposion/proposals/forms.py +++ b/symposion/proposals/forms.py @@ -1,5 +1,6 @@ from django import forms from django.db.models import Q +from django.utils.translation import ugettext_lazy as _ from symposion.proposals.models import SupportingDocument # from markitup.widgets import MarkItUpWidget @@ -11,7 +12,7 @@ from symposion.proposals.models import SupportingDocument class AddSpeakerForm(forms.Form): email = forms.EmailField( - label="Email address of new speaker (use their email address, not yours)" + label=_("Email address of new speaker (use their email address, not yours)") ) def __init__(self, *args, **kwargs): @@ -26,7 +27,7 @@ class AddSpeakerForm(forms.Form): ).exists() if exists: raise forms.ValidationError( - "This email address has already been invited to your talk proposal" + _("This email address has already been invited to your talk proposal") ) return value diff --git a/symposion/proposals/models.py b/symposion/proposals/models.py index 7dea87cd..a8b4f8e0 100644 --- a/symposion/proposals/models.py +++ b/symposion/proposals/models.py @@ -31,12 +31,12 @@ class ProposalSection(models.Model): * closed is NULL or False """ - section = models.OneToOneField(Section) + section = models.OneToOneField(Section, verbose_name=_("Section")) - start = models.DateTimeField(null=True, blank=True) - end = models.DateTimeField(null=True, blank=True) - closed = models.NullBooleanField() - published = models.NullBooleanField() + start = models.DateTimeField(null=True, blank=True, verbose_name=_("Start")) + end = models.DateTimeField(null=True, blank=True, verbose_name=_("End")) + closed = models.NullBooleanField(verbose_name=_("Closed")) + published = models.NullBooleanField(verbose_name=_("Published")) @classmethod def available(cls): @@ -67,10 +67,10 @@ class ProposalKind(models.Model): to distinguish the section as well as the kind. """ - section = models.ForeignKey(Section, related_name="proposal_kinds") + section = models.ForeignKey(Section, related_name="proposal_kinds", verbose_name=_("Section")) name = models.CharField(_("Name"), max_length=100) - slug = models.SlugField() + slug = models.SlugField(verbose_name=_("Slug")) def __unicode__(self): return self.name @@ -80,9 +80,9 @@ class ProposalBase(models.Model): objects = InheritanceManager() - kind = models.ForeignKey(ProposalKind) + kind = models.ForeignKey(ProposalKind, verbose_name=_("Kind")) - title = models.CharField(max_length=100) + title = models.CharField(max_length=100, verbose_name=_("Title")) description = models.TextField( _("Brief Description"), max_length=400, # @@@ need to enforce 400 in UI @@ -96,6 +96,7 @@ class ProposalBase(models.Model): "target='_blank'>Markdown.") ) additional_notes = MarkupField( + _("Addtional Notes"), blank=True, help_text=_("Anything else you'd like the program committee to know when making their " "selection: your past experience, etc. This is not made public. Edit using " @@ -105,8 +106,9 @@ class ProposalBase(models.Model): submitted = models.DateTimeField( default=now, editable=False, + verbose_name=_("Submitted") ) - speaker = models.ForeignKey(Speaker, related_name="proposals") + speaker = models.ForeignKey(Speaker, related_name="proposals", verbose_name=_("Speaker")) def additional_speaker_validator(self, a_speaker): if a_speaker.speaker.email == self.speaker.email: @@ -115,8 +117,9 @@ class ProposalBase(models.Model): raise ValidationError(_("%s has already been in speakers.") % a_speaker.speaker.email) additional_speakers = models.ManyToManyField(Speaker, through="AdditionalSpeaker", - blank=True, validators=[additional_speaker_validator]) - cancelled = models.BooleanField(default=False) + blank=True, verbose_name=_("Addtional speakers"), + validators=[additional_speaker_validator]) + cancelled = models.BooleanField(default=False, verbose_name=_("Cancelled")) def can_edit(self): return True @@ -170,12 +173,14 @@ class AdditionalSpeaker(models.Model): (SPEAKING_STATUS_DECLINED, _("Declined")), ] - speaker = models.ForeignKey(Speaker) - proposalbase = models.ForeignKey(ProposalBase) - status = models.IntegerField(choices=SPEAKING_STATUS, default=SPEAKING_STATUS_PENDING) + speaker = models.ForeignKey(Speaker, verbose_name=_("Speaker")) + proposalbase = models.ForeignKey(ProposalBase, verbose_name=_("Proposalbase")) + status = models.IntegerField(choices=SPEAKING_STATUS, default=SPEAKING_STATUS_PENDING, verbose_name=_("Status")) class Meta: unique_together = ("speaker", "proposalbase") + verbose_name = _("Addtional speaker") + verbose_name_plural = _("Additional speakers") def __unicode__(self): if self.status is self.SPEAKING_STATUS_PENDING: @@ -194,14 +199,14 @@ def uuid_filename(instance, filename): class SupportingDocument(models.Model): - proposal = models.ForeignKey(ProposalBase, related_name="supporting_documents") + proposal = models.ForeignKey(ProposalBase, related_name="supporting_documents", verbose_name=_("Proposal")) - uploaded_by = models.ForeignKey(User) + uploaded_by = models.ForeignKey(User, verbose_name=_("Uploaded by")) - created_at = models.DateTimeField(default=now) + created_at = models.DateTimeField(default=now, verbose_name=_("Created at")) - file = models.FileField(upload_to=uuid_filename) - description = models.CharField(max_length=140) + file = models.FileField(upload_to=uuid_filename, verbose_name=_("File")) + description = models.CharField(max_length=140, verbose_name=_("Description")) def download_url(self): return reverse("proposal_document_download", diff --git a/symposion/proposals/views.py b/symposion/proposals/views.py index 46c3c1c6..1d07b23d 100644 --- a/symposion/proposals/views.py +++ b/symposion/proposals/views.py @@ -87,7 +87,7 @@ def proposal_submit_kind(request, kind_slug): proposal.speaker = speaker_profile proposal.save() form.save_m2m() - messages.success(request, "Proposal submitted.") + messages.success(request, _("Proposal submitted.")) if "add-speakers" in request.POST: return redirect("proposal_speaker_manage", proposal.pk) return redirect("dashboard") diff --git a/symposion/reviews/apps.py b/symposion/reviews/apps.py index 683b0c0f..80fab5c3 100644 --- a/symposion/reviews/apps.py +++ b/symposion/reviews/apps.py @@ -1,7 +1,8 @@ from django.apps import AppConfig +from django.utils.translation import ugettext_lazy as _ class ReviewsConfig(AppConfig): name = "symposion.reviews" label = "symposion_reviews" - verbose_name = "Symposion Reviews" + verbose_name = _("Symposion Reviews") diff --git a/symposion/reviews/forms.py b/symposion/reviews/forms.py index a705333c..f49cdab8 100644 --- a/symposion/reviews/forms.py +++ b/symposion/reviews/forms.py @@ -1,4 +1,5 @@ from django import forms +from django.utils.translation import ugettext_lazy as _ from markitup.widgets import MarkItUpWidget @@ -35,6 +36,7 @@ class SpeakerCommentForm(forms.ModelForm): class BulkPresentationForm(forms.Form): talk_ids = forms.CharField( + label=_("Talk ids"), max_length=500, - help_text="Provide a comma seperated list of talk ids to accept." + help_text=_("Provide a comma seperated list of talk ids to accept.") ) diff --git a/symposion/reviews/models.py b/symposion/reviews/models.py index 1537ae98..48602639 100644 --- a/symposion/reviews/models.py +++ b/symposion/reviews/models.py @@ -7,6 +7,7 @@ from django.db.models import Q from django.db.models.signals import post_save from django.contrib.auth.models import User +from django.utils.translation import ugettext_lazy as _ from markitup.fields import MarkupField @@ -31,10 +32,10 @@ class Votes(object): MINUS_ONE = u"−1" CHOICES = [ - (PLUS_ONE, u"+1 — Good proposal and I will argue for it to be accepted."), - (PLUS_ZERO, u"+0 — OK proposal, but I will not argue for it to be accepted."), - (MINUS_ZERO, u"−0 — Weak proposal, but I will not argue strongly against acceptance."), - (MINUS_ONE, u"−1 — Serious issues and I will argue to reject this proposal."), + (PLUS_ONE, _("+1 — Good proposal and I will argue for it to be accepted.")), + (PLUS_ZERO, _("+0 — OK proposal, but I will not argue for it to be accepted.")), + (MINUS_ZERO, _("−0 — Weak proposal, but I will not argue strongly against acceptance.")), + (MINUS_ONE, _("−1 — Serious issues and I will argue to reject this proposal.")), ] VOTES = Votes() @@ -47,18 +48,18 @@ class ReviewAssignment(models.Model): NUM_REVIEWERS = 3 ORIGIN_CHOICES = [ - (AUTO_ASSIGNED_INITIAL, "auto-assigned, initial"), - (OPT_IN, "opted-in"), - (AUTO_ASSIGNED_LATER, "auto-assigned, later"), + (AUTO_ASSIGNED_INITIAL, _("auto-assigned, initial")), + (OPT_IN, _("opted-in")), + (AUTO_ASSIGNED_LATER, _("auto-assigned, later")), ] - proposal = models.ForeignKey(ProposalBase) - user = models.ForeignKey(User) + proposal = models.ForeignKey(ProposalBase, verbose_name=_("Proposal")) + user = models.ForeignKey(User, verbose_name=_("User")) - origin = models.IntegerField(choices=ORIGIN_CHOICES) + origin = models.IntegerField(choices=ORIGIN_CHOICES, verbose_name=_("Origin")) - assigned_at = models.DateTimeField(default=datetime.now) - opted_out = models.BooleanField(default=False) + assigned_at = models.DateTimeField(default=datetime.now, verbose_name=_("Assigned at")) + opted_out = models.BooleanField(default=False, verbose_name=_("Opted out")) @classmethod def create_assignments(cls, proposal, origin=AUTO_ASSIGNED_INITIAL): @@ -92,27 +93,29 @@ class ReviewAssignment(models.Model): class ProposalMessage(models.Model): - proposal = models.ForeignKey(ProposalBase, related_name="messages") - user = models.ForeignKey(User) + proposal = models.ForeignKey(ProposalBase, related_name="messages", verbose_name=_("Proposal")) + user = models.ForeignKey(User, verbose_name=_("User")) - message = MarkupField() - submitted_at = models.DateTimeField(default=datetime.now, editable=False) + message = MarkupField(verbose_name=_("Message")) + submitted_at = models.DateTimeField(default=datetime.now, editable=False, verbose_name=_("Submitted at")) class Meta: ordering = ["submitted_at"] + verbose_name = _("proposal message") + verbose_name_plural = _("proposal messages") class Review(models.Model): VOTES = VOTES - proposal = models.ForeignKey(ProposalBase, related_name="reviews") - user = models.ForeignKey(User) + proposal = models.ForeignKey(ProposalBase, related_name="reviews", verbose_name=_("Proposal")) + user = models.ForeignKey(User, verbose_name=_("User")) # No way to encode "-0" vs. "+0" into an IntegerField, and I don't feel # like some complicated encoding system. - vote = models.CharField(max_length=2, blank=True, choices=VOTES.CHOICES) - comment = MarkupField() - submitted_at = models.DateTimeField(default=datetime.now, editable=False) + vote = models.CharField(max_length=2, blank=True, choices=VOTES.CHOICES, verbose_name=_("Vote")) + comment = MarkupField(verbose_name=_("Comment")) + submitted_at = models.DateTimeField(default=datetime.now, editable=False, verbose_name=_("Submitted at")) def save(self, **kwargs): if self.vote: @@ -180,20 +183,26 @@ class Review(models.Model): def section(self): return self.proposal.kind.section.slug + class Meta: + verbose_name = _("review") + verbose_name_plural = _("reviews") + class LatestVote(models.Model): VOTES = VOTES - proposal = models.ForeignKey(ProposalBase, related_name="votes") - user = models.ForeignKey(User) + proposal = models.ForeignKey(ProposalBase, related_name="votes", verbose_name=_("Proposal")) + user = models.ForeignKey(User, verbose_name=_("User")) # No way to encode "-0" vs. "+0" into an IntegerField, and I don't feel # like some complicated encoding system. - vote = models.CharField(max_length=2, choices=VOTES.CHOICES) - submitted_at = models.DateTimeField(default=datetime.now, editable=False) + vote = models.CharField(max_length=2, choices=VOTES.CHOICES, verbose_name=_("Vote")) + submitted_at = models.DateTimeField(default=datetime.now, editable=False, verbose_name=_("Submitted at")) class Meta: unique_together = [("proposal", "user")] + verbose_name = _("latest vote") + verbose_name_plural = _("latest votes") def css_class(self): return { @@ -205,25 +214,25 @@ class LatestVote(models.Model): class ProposalResult(models.Model): - proposal = models.OneToOneField(ProposalBase, related_name="result") - score = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal("0.00")) - comment_count = models.PositiveIntegerField(default=0) - vote_count = models.PositiveIntegerField(default=0) - plus_one = models.PositiveIntegerField(default=0) - plus_zero = models.PositiveIntegerField(default=0) - minus_zero = models.PositiveIntegerField(default=0) - minus_one = models.PositiveIntegerField(default=0) + proposal = models.OneToOneField(ProposalBase, related_name="result", verbose_name=_("Proposal")) + score = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal("0.00"), verbose_name=_("Score")) + comment_count = models.PositiveIntegerField(default=0, verbose_name=_("Comment count")) + vote_count = models.PositiveIntegerField(default=0, verbose_name=_("Vote count")) + plus_one = models.PositiveIntegerField(default=0, verbose_name=_("Plus one")) + plus_zero = models.PositiveIntegerField(default=0, verbose_name=_("Plus zero")) + minus_zero = models.PositiveIntegerField(default=0, verbose_name=_("Minus zero")) + minus_one = models.PositiveIntegerField(default=0, verbose_name=_("Minus one")) accepted = models.NullBooleanField(choices=[ (True, "accepted"), (False, "rejected"), (None, "undecided"), - ], default=None) + ], default=None, verbose_name=_("Accepted")) status = models.CharField(max_length=20, choices=[ - ("accepted", "accepted"), - ("rejected", "rejected"), - ("undecided", "undecided"), - ("standby", "standby"), - ], default="undecided") + ("accepted", _("accepted")), + ("rejected", _("rejected")), + ("undecided", _("undecided")), + ("standby", _("standby")), + ], default="undecided", verbose_name=_("Status")) @classmethod def full_calculate(cls): @@ -279,35 +288,47 @@ class ProposalResult(models.Model): model = self.__class__ model._default_manager.filter(pk=self.pk).update(score=ProposalScoreExpression()) + class Meta: + verbose_name = _("proposal_result") + verbose_name_plural = _("proposal_results") + class Comment(models.Model): - proposal = models.ForeignKey(ProposalBase, related_name="comments") - commenter = models.ForeignKey(User) - text = MarkupField() + proposal = models.ForeignKey(ProposalBase, related_name="comments", verbose_name=_("Proposal")) + commenter = models.ForeignKey(User, verbose_name=_("Commenter")) + text = MarkupField(verbose_name=_("Text")) # Or perhaps more accurately, can the user see this comment. - public = models.BooleanField(choices=[(True, "public"), (False, "private")], default=False) - commented_at = models.DateTimeField(default=datetime.now) + public = models.BooleanField(choices=[(True, _("public")), (False, _("private"))], default=False, verbose_name=_("Public")) + commented_at = models.DateTimeField(default=datetime.now, verbose_name=_("Commented at")) + + class Meta: + verbose_name = _("comment") + verbose_name_plural = _("comments") class NotificationTemplate(models.Model): - label = models.CharField(max_length=100) - from_address = models.EmailField() - subject = models.CharField(max_length=100) - body = models.TextField() + label = models.CharField(max_length=100, verbose_name=_("Label")) + from_address = models.EmailField(verbose_name=_("From address")) + subject = models.CharField(max_length=100, verbose_name=_("Subject")) + body = models.TextField(verbose_name=_("Body")) + + class Meta: + verbose_name = _("notification template") + verbose_name_plural = _("notification templates") class ResultNotification(models.Model): - proposal = models.ForeignKey(ProposalBase, related_name="notifications") + proposal = models.ForeignKey(ProposalBase, related_name="notifications", verbose_name=_("Proposal")) template = models.ForeignKey(NotificationTemplate, null=True, blank=True, - on_delete=models.SET_NULL) - timestamp = models.DateTimeField(default=datetime.now) - to_address = models.EmailField() - from_address = models.EmailField() - subject = models.CharField(max_length=100) - body = models.TextField() + on_delete=models.SET_NULL, verbose_name=_("Template")) + timestamp = models.DateTimeField(default=datetime.now, verbose_name=_("Timestamp")) + to_address = models.EmailField(verbose_name=_("To address")) + from_address = models.EmailField(verbose_name=_("From address")) + subject = models.CharField(max_length=100, verbose_name=_("Subject")) + body = models.TextField(verbose_name=_("Body")) def recipients(self): for speaker in self.proposal.speakers(): diff --git a/symposion/schedule/models.py b/symposion/schedule/models.py index a0f88e81..efa2d24c 100644 --- a/symposion/schedule/models.py +++ b/symposion/schedule/models.py @@ -3,6 +3,7 @@ import datetime from django.core.exceptions import ObjectDoesNotExist from django.contrib.auth.models import User from django.db import models +from django.utils.translation import ugettext_lazy as _ from markitup.fields import MarkupField @@ -13,21 +14,23 @@ from symposion.speakers.models import Speaker class Schedule(models.Model): - section = models.OneToOneField(Section) - published = models.BooleanField(default=True) - hidden = models.BooleanField("Hide schedule from overall conference view", default=False) + section = models.OneToOneField(Section, verbose_name=_("Section")) + published = models.BooleanField(default=True, verbose_name=_("Published")) + hidden = models.BooleanField(_("Hide schedule from overall conference view"), default=False) def __unicode__(self): return u"%s Schedule" % self.section class Meta: ordering = ["section"] + verbose_name = _('Schedule') + verbose_name_plural = _('Schedules') class Day(models.Model): - schedule = models.ForeignKey(Schedule) - date = models.DateField() + schedule = models.ForeignKey(Schedule, verbose_name=_("Schedule")) + date = models.DateField(verbose_name=_("Date")) def __unicode__(self): return u"%s" % self.date @@ -35,17 +38,23 @@ class Day(models.Model): class Meta: unique_together = [("schedule", "date")] ordering = ["date"] + verbose_name = _("date") + verbose_name_plural = _("dates") class Room(models.Model): - schedule = models.ForeignKey(Schedule) - name = models.CharField(max_length=65) - order = models.PositiveIntegerField() + schedule = models.ForeignKey(Schedule, verbose_name=_("Schedule")) + name = models.CharField(max_length=65, verbose_name=_("Name")) + order = models.PositiveIntegerField(verbose_name=_("Order")) def __unicode__(self): return self.name + class Meta: + verbose_name = _("Room") + verbose_name_plural = _("Rooms") + class SlotKind(models.Model): """ @@ -53,20 +62,24 @@ class SlotKind(models.Model): break, lunch, or X-minute talk. """ - schedule = models.ForeignKey(Schedule) - label = models.CharField(max_length=50) + schedule = models.ForeignKey(Schedule, verbose_name=_("schedule")) + label = models.CharField(max_length=50, verbose_name=_("Label")) def __unicode__(self): return self.label + class Meta: + verbose_name = _("Slot kind") + verbose_name_plural = _("Slot kinds") + class Slot(models.Model): - day = models.ForeignKey(Day) - kind = models.ForeignKey(SlotKind) - start = models.TimeField() - end = models.TimeField() - content_override = MarkupField(blank=True) + day = models.ForeignKey(Day, verbose_name=_("Day")) + kind = models.ForeignKey(SlotKind, verbose_name=_("Kind")) + start = models.TimeField(verbose_name=_("Start")) + end = models.TimeField(verbose_name=_("End")) + content_override = MarkupField(blank=True, verbose_name=_("Content override")) def assign(self, content): """ @@ -130,6 +143,8 @@ class Slot(models.Model): class Meta: ordering = ["day", "start", "end"] + verbose_name = _("slot") + verbose_name_plural = _("slots") class SlotRoom(models.Model): @@ -137,8 +152,8 @@ class SlotRoom(models.Model): Links a slot with a room. """ - slot = models.ForeignKey(Slot) - room = models.ForeignKey(Room) + slot = models.ForeignKey(Slot, verbose_name=_("Slot")) + room = models.ForeignKey(Room, verbose_name=_("Room")) def __unicode__(self): return u"%s %s" % (self.room, self.slot) @@ -146,20 +161,22 @@ class SlotRoom(models.Model): class Meta: unique_together = [("slot", "room")] ordering = ["slot", "room__order"] + verbose_name = _("Slot room") + verbose_name_plural = _("Slot rooms") class Presentation(models.Model): - slot = models.OneToOneField(Slot, null=True, blank=True, related_name="content_ptr") - title = models.CharField(max_length=100) - description = MarkupField() - abstract = MarkupField() - speaker = models.ForeignKey(Speaker, related_name="presentations") + slot = models.OneToOneField(Slot, null=True, blank=True, related_name="content_ptr", verbose_name=_("Slot")) + title = models.CharField(max_length=100, verbose_name=_("Title")) + description = MarkupField(verbose_name=_("Description")) + abstract = MarkupField(verbose_name=_("Abstract")) + speaker = models.ForeignKey(Speaker, related_name="presentations", verbose_name=_("Speaker")) additional_speakers = models.ManyToManyField(Speaker, related_name="copresentations", - blank=True) - cancelled = models.BooleanField(default=False) - proposal_base = models.OneToOneField(ProposalBase, related_name="presentation") - section = models.ForeignKey(Section, related_name="presentations") + blank=True, verbose_name=_("Additional speakers")) + cancelled = models.BooleanField(default=False, verbose_name=_("Cancelled")) + proposal_base = models.OneToOneField(ProposalBase, related_name="presentation", verbose_name=_("Proposal base")) + section = models.ForeignKey(Section, related_name="presentations", verbose_name=_("Section")) @property def number(self): @@ -182,12 +199,14 @@ class Presentation(models.Model): class Meta: ordering = ["slot"] + verbose_name = _("presentation") + verbose_name_plural = _("presentations") class Session(models.Model): - day = models.ForeignKey(Day, related_name="sessions") - slots = models.ManyToManyField(Slot, related_name="sessions") + day = models.ForeignKey(Day, related_name="sessions", verbose_name=_("Day")) + slots = models.ManyToManyField(Slot, related_name="sessions", verbose_name=_("Slots")) def sorted_slots(self): return self.slots.order_by("start") @@ -217,6 +236,10 @@ class Session(models.Model): ) return u"" + class Meta: + verbose_name = _("Session") + verbose_name_plural = _("Sessions") + class SessionRole(models.Model): @@ -224,19 +247,21 @@ class SessionRole(models.Model): SESSION_ROLE_RUNNER = 2 SESSION_ROLE_TYPES = [ - (SESSION_ROLE_CHAIR, "Session Chair"), - (SESSION_ROLE_RUNNER, "Session Runner"), + (SESSION_ROLE_CHAIR, _("Session Chair")), + (SESSION_ROLE_RUNNER, _("Session Runner")), ] - session = models.ForeignKey(Session) - user = models.ForeignKey(User) - role = models.IntegerField(choices=SESSION_ROLE_TYPES) - status = models.NullBooleanField() + session = models.ForeignKey(Session, verbose_name=_("Session")) + user = models.ForeignKey(User, verbose_name=_("User")) + role = models.IntegerField(choices=SESSION_ROLE_TYPES, verbose_name=_("Role")) + status = models.NullBooleanField(verbose_name=_("Status")) submitted = models.DateTimeField(default=datetime.datetime.now) class Meta: unique_together = [("session", "user", "role")] + verbose_name = _("Session role") + verbose_name_plural = _("Session roles") def __unicode__(self): return u"%s %s: %s" % (self.user, self.session, diff --git a/symposion/speakers/apps.py b/symposion/speakers/apps.py index b4abf5d5..c772a12a 100644 --- a/symposion/speakers/apps.py +++ b/symposion/speakers/apps.py @@ -1,7 +1,8 @@ from django.apps import AppConfig +from django.utils.translation import ugettext_lazy as _ class SpeakersConfig(AppConfig): name = "symposion.speakers" label = "symposion_speakers" - verbose_name = "Symposion Speakers" + verbose_name = _("Symposion Speakers") diff --git a/symposion/speakers/models.py b/symposion/speakers/models.py index 0887ef45..48121f2c 100644 --- a/symposion/speakers/models.py +++ b/symposion/speakers/models.py @@ -1,4 +1,5 @@ import datetime +from django.utils.translation import ugettext_lazy as _ from django.db import models from django.core.urlresolvers import reverse @@ -15,24 +16,28 @@ class Speaker(models.Model): (2, "Two") ] - user = models.OneToOneField(User, null=True, related_name="speaker_profile") - name = models.CharField(max_length=100, help_text=("As you would like it to appear in the " - "conference program.")) - biography = MarkupField(blank=True, help_text=("A little bit about you. Edit using " - "" - "Markdown.")) - photo = models.ImageField(upload_to="speaker_photos", blank=True) - annotation = models.TextField() # staff only - invite_email = models.CharField(max_length=200, unique=True, null=True, db_index=True) - invite_token = models.CharField(max_length=40, db_index=True) + user = models.OneToOneField(User, null=True, related_name="speaker_profile", verbose_name=_("User")) + name = models.CharField(verbose_name=_("Name"), max_length=100, + help_text=_("As you would like it to appear in the" + " conference program.")) + biography = MarkupField(blank=True, help_text=_("A little bit about you. Edit using " + "" + "Markdown."), verbose_name=_("Biography")) + photo = models.ImageField(upload_to="speaker_photos", blank=True, verbose_name=_("Photo")) + annotation = models.TextField(verbose_name=_("Annotation")) # staff only + invite_email = models.CharField(max_length=200, unique=True, null=True, db_index=True, verbose_name=_("Invite_email")) + invite_token = models.CharField(max_length=40, db_index=True, verbose_name=_("Invite token")) created = models.DateTimeField( default=datetime.datetime.now, - editable=False + editable=False, + verbose_name=_("Created") ) class Meta: ordering = ['name'] + verbose_name = _("Speaker") + verbose_name_plural = _("Speakers") def __unicode__(self): if self.user: diff --git a/symposion/speakers/views.py b/symposion/speakers/views.py index fbd4c57c..6d48c1dd 100644 --- a/symposion/speakers/views.py +++ b/symposion/speakers/views.py @@ -5,6 +5,7 @@ from django.shortcuts import render, redirect, get_object_or_404 from django.contrib import messages from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User +from django.utils.translation import ugettext_lazy as _ from symposion.proposals.models import ProposalBase from symposion.speakers.forms import SpeakerForm @@ -33,7 +34,7 @@ def speaker_create(request): if not found: speaker.invite_email = None speaker.save() - messages.success(request, "Speaker profile created.") + messages.success(request, _("Speaker profile created.")) return redirect("dashboard") else: form = SpeakerForm(initial={"name": request.user.get_full_name()}) @@ -61,7 +62,7 @@ def speaker_create_staff(request, pk): speaker = form.save(commit=False) speaker.user = user speaker.save() - messages.success(request, "Speaker profile created.") + messages.success(request, _("Speaker profile created.")) return redirect("user_list") else: form = SpeakerForm(initial={"name": user.get_full_name()}) @@ -88,8 +89,8 @@ def speaker_create_token(request, token): ).update( speaker=existing_speaker ) - messages.info(request, ("You have been associated with all pending " - "talk proposals")) + messages.info(request, _("You have been associated with all pending " + "talk proposals")) return redirect("dashboard") else: if not request.user.is_authenticated(): diff --git a/symposion/sponsorship/admin.py b/symposion/sponsorship/admin.py index 77a84b8d..0e38ad04 100644 --- a/symposion/sponsorship/admin.py +++ b/symposion/sponsorship/admin.py @@ -61,9 +61,9 @@ class SponsorAdmin(admin.ModelAdmin): # @@@ kinda ugly but using choices= on NullBooleanField is broken form = super(SponsorAdmin, self).get_form(*args, **kwargs) form.base_fields["active"].widget.choices = [ - (u"1", "unreviewed"), - (u"2", "approved"), - (u"3", "rejected") + ("1", _("unreviewed")), + ("2", _("approved")), + ("3", _("rejected")) ] return form diff --git a/symposion/sponsorship/apps.py b/symposion/sponsorship/apps.py index 80bf19d1..92ee49cd 100644 --- a/symposion/sponsorship/apps.py +++ b/symposion/sponsorship/apps.py @@ -1,7 +1,9 @@ +from __future__ import unicode_literals from django.apps import AppConfig +from django.utils.translation import ugettext_lazy as _ class SponsorshipConfig(AppConfig): name = "symposion.sponsorship" label = "symposion_sponsorship" - verbose_name = "Symposion Sponsorship" + verbose_name = _("Symposion Sponsorship") diff --git a/symposion/sponsorship/forms.py b/symposion/sponsorship/forms.py index 33b52f42..336f7ff5 100644 --- a/symposion/sponsorship/forms.py +++ b/symposion/sponsorship/forms.py @@ -2,6 +2,7 @@ from django import forms from django.forms.models import inlineformset_factory, BaseInlineFormSet from django.contrib.admin.widgets import AdminFileWidget +from django.utils.translation import ugettext_lazy as _ from symposion.sponsorship.models import Sponsor, SponsorBenefit @@ -61,7 +62,7 @@ class SponsorBenefitsInlineFormSet(BaseInlineFormSet): # provide word limit as help_text if form.instance.benefit.type == "text" and form.instance.max_words: - form.fields[field].help_text = u"maximum %s words" % form.instance.max_words + form.fields[field].help_text = _("maximum %s words") % form.instance.max_words # use admin file widget that shows currently uploaded file if field == "upload": diff --git a/symposion/sponsorship/models.py b/symposion/sponsorship/models.py index d4161176..13bace02 100644 --- a/symposion/sponsorship/models.py +++ b/symposion/sponsorship/models.py @@ -16,16 +16,16 @@ from symposion.sponsorship.managers import SponsorManager class SponsorLevel(models.Model): - conference = models.ForeignKey(Conference, verbose_name=_("conference")) - name = models.CharField(_("name"), max_length=100) - order = models.IntegerField(_("order"), default=0) - cost = models.PositiveIntegerField(_("cost")) - description = models.TextField(_("description"), blank=True, help_text=_("This is private.")) + conference = models.ForeignKey(Conference, verbose_name=_("Conference")) + name = models.CharField(_("Name"), max_length=100) + order = models.IntegerField(_("Order"), default=0) + cost = models.PositiveIntegerField(_("Cost")) + description = models.TextField(_("Description"), blank=True, help_text=_("This is private.")) class Meta: ordering = ["conference", "order"] - verbose_name = _("sponsor level") - verbose_name_plural = _("sponsor levels") + verbose_name = _("Sponsor level") + verbose_name_plural = _("Sponsor levels") def __unicode__(self): return self.name @@ -36,22 +36,22 @@ class SponsorLevel(models.Model): class Sponsor(models.Model): - applicant = models.ForeignKey(User, related_name="sponsorships", verbose_name=_("applicant"), + applicant = models.ForeignKey(User, related_name="sponsorships", verbose_name=_("Applicant"), null=True) name = models.CharField(_("Sponsor Name"), max_length=100) display_url = models.URLField(_("display URL"), blank=True) - external_url = models.URLField(_("external URL")) - annotation = models.TextField(_("annotation"), blank=True) + external_url = models.URLField(_("External URL")) + annotation = models.TextField(_("Annotation"), blank=True) contact_name = models.CharField(_("Contact Name"), max_length=100) - contact_email = models.EmailField(_(u"Contact Email")) + contact_email = models.EmailField(_("Contact Email")) level = models.ForeignKey(SponsorLevel, verbose_name=_("level")) added = models.DateTimeField(_("added"), default=datetime.datetime.now) active = models.BooleanField(_("active"), default=False) # Denormalization (this assumes only one logo) sponsor_logo = models.ForeignKey("SponsorBenefit", related_name="+", null=True, blank=True, - editable=False) + editable=False, verbose_name=_("Sponsor logo")) objects = SponsorManager() @@ -59,8 +59,8 @@ class Sponsor(models.Model): return self.name class Meta: - verbose_name = _("sponsor") - verbose_name_plural = _("sponsors") + verbose_name = _("Sponsor") + verbose_name_plural = _("Sponsors") def get_absolute_url(self): if self.active: @@ -151,12 +151,12 @@ post_save.connect(_check_level_change, sender=Sponsor) BENEFIT_TYPE_CHOICES = [ - ("text", "Text"), - ("richtext", "Rich Text"), - ("file", "File"), - ("weblogo", "Web Logo"), - ("simple", "Simple"), - ("option", "Option") + ("text", _("Text")), + ("file", _("File")), + ("richtext", _("Rich Text")), + ("weblogo", _("Web Logo")), + ("simple", _("Simple")), + ("option", _("Option")) ] CONTENT_TYPE_CHOICES = [ @@ -168,10 +168,10 @@ CONTENT_TYPE_CHOICES = [ class Benefit(models.Model): - name = models.CharField(_("name"), max_length=100) - description = models.TextField(_("description"), blank=True) - type = models.CharField(_("type"), choices=BENEFIT_TYPE_CHOICES, - max_length=10, default="simple") + name = models.CharField(_("Name"), max_length=100) + description = models.TextField(_("Description"), blank=True) + type = models.CharField(_("Type"), choices=BENEFIT_TYPE_CHOICES, max_length=10, + default="simple") content_type = models.CharField(_("content type"), choices=CONTENT_TYPE_CHOICES, max_length=20, default="simple") @@ -181,15 +181,17 @@ class Benefit(models.Model): class BenefitLevel(models.Model): - benefit = models.ForeignKey(Benefit, related_name="benefit_levels", verbose_name=_("benefit")) - level = models.ForeignKey(SponsorLevel, related_name="benefit_levels", verbose_name=_("level")) + benefit = models.ForeignKey(Benefit, related_name="benefit_levels", verbose_name=_("Benefit")) + level = models.ForeignKey(SponsorLevel, related_name="benefit_levels", verbose_name=_("Level")) # default limits for this benefit at given level - max_words = models.PositiveIntegerField(_("max words"), blank=True, null=True) - other_limits = models.CharField(_("other limits"), max_length=200, blank=True) + max_words = models.PositiveIntegerField(_("Max words"), blank=True, null=True) + other_limits = models.CharField(_("Other limits"), max_length=200, blank=True) class Meta: ordering = ["level"] + verbose_name = _("Benefit level") + verbose_name_plural = _("Benefit levels") def __unicode__(self): return u"%s - %s" % (self.level, self.benefit) @@ -197,21 +199,23 @@ class BenefitLevel(models.Model): class SponsorBenefit(models.Model): - sponsor = models.ForeignKey(Sponsor, related_name="sponsor_benefits", verbose_name=_("sponsor")) - benefit = models.ForeignKey(Benefit, related_name="sponsor_benefits", verbose_name=_("benefit")) - active = models.BooleanField(default=True) + sponsor = models.ForeignKey(Sponsor, related_name="sponsor_benefits", verbose_name=_("Sponsor")) + benefit = models.ForeignKey(Benefit, related_name="sponsor_benefits", verbose_name=_("Benefit")) + active = models.BooleanField(default=True, verbose_name=_("Active")) # Limits: will initially be set to defaults from corresponding BenefitLevel - max_words = models.PositiveIntegerField(_("max words"), blank=True, null=True) - other_limits = models.CharField(_("other limits"), max_length=200, blank=True) + max_words = models.PositiveIntegerField(_("Max words"), blank=True, null=True) + other_limits = models.CharField(_("Other limits"), max_length=200, blank=True) # Data: zero or one of these fields will be used, depending on the # type of the Benefit (text, file, or simple) - text = models.TextField(_("text"), blank=True) - upload = models.FileField(_("file"), blank=True, upload_to="sponsor_files") + text = models.TextField(_("Text"), blank=True) + upload = models.FileField(_("File"), blank=True, upload_to="sponsor_files") class Meta: ordering = ["-active"] + verbose_name = _("Sponsor benefit") + verbose_name_plural = _("Sponsor benefits") def __unicode__(self): return u"%s - %s" % (self.sponsor, self.benefit) @@ -220,8 +224,8 @@ class SponsorBenefit(models.Model): num_words = len(self.text.split()) if self.max_words and num_words > self.max_words: raise ValidationError( - "Sponsorship level only allows for %s words, you provided %d." % ( - self.max_words, num_words)) + _("Sponsorship level only allows for %(word)s words, you provided %(num)d.") % { + "word": self.max_words, "num": num_words}) def data_fields(self): """ diff --git a/symposion/sponsorship/views.py b/symposion/sponsorship/views.py index bf74ec3a..ae5597e7 100644 --- a/symposion/sponsorship/views.py +++ b/symposion/sponsorship/views.py @@ -6,16 +6,14 @@ import time from zipfile import ZipFile, ZipInfo from django.conf import settings - +from django.contrib import messages +from django.contrib.admin.views.decorators import staff_member_required +from django.contrib.auth.decorators import login_required from django.http import Http404, HttpResponse from django.shortcuts import render_to_response, redirect, get_object_or_404 from django.template import RequestContext from django.utils.translation import ugettext_lazy as _ -from django.contrib import messages -from django.contrib.admin.views.decorators import staff_member_required -from django.contrib.auth.decorators import login_required - from symposion.sponsorship.forms import SponsorApplicationForm, \ SponsorDetailsForm, SponsorBenefitsFormSet from symposion.sponsorship.models import Benefit, Sponsor, SponsorBenefit, \ @@ -90,7 +88,7 @@ def sponsor_detail(request, pk): form.save() formset.save() - messages.success(request, "Sponsorship details have been updated") + messages.success(request, _("Sponsorship details have been updated")) return redirect("dashboard") else: diff --git a/symposion/teams/forms.py b/symposion/teams/forms.py index a9080626..5ba8ccae 100644 --- a/symposion/teams/forms.py +++ b/symposion/teams/forms.py @@ -2,6 +2,7 @@ from django import forms from django.utils.html import escape from django.utils.safestring import mark_safe +from django.utils.translation import ugettext_lazy as _ from django.contrib.auth.models import User @@ -10,8 +11,9 @@ from symposion.teams.models import Membership class TeamInvitationForm(forms.Form): - email = forms.EmailField(help_text=("email address must be that of an account on this " - "conference site")) + email = forms.EmailField(label=_("Email"), + help_text=_("email address must be that of an account on this " + "conference site")) def __init__(self, *args, **kwargs): self.team = kwargs.pop("team") @@ -22,7 +24,7 @@ class TeamInvitationForm(forms.Form): email = cleaned_data.get("email") if email is None: - raise forms.ValidationError("valid email address required") + raise forms.ValidationError(_("valid email address required")) try: user = User.objects.get(email=email) @@ -30,16 +32,16 @@ class TeamInvitationForm(forms.Form): # eventually we can invite them but for now assume they are # already on the site raise forms.ValidationError( - mark_safe("no account with email address %s found on this conference " - "site" % escape(email))) + mark_safe(_("no account with email address %s found on this conference " + "site") % escape(email))) state = self.team.get_state_for_user(user) if state in ["member", "manager"]: - raise forms.ValidationError("user already in team") + raise forms.ValidationError(_("user already in team")) if state in ["invited"]: - raise forms.ValidationError("user already invited to team") + raise forms.ValidationError(_("user already invited to team")) self.user = user self.state = state diff --git a/symposion/teams/models.py b/symposion/teams/models.py index 8c344cc4..fbbc4c45 100644 --- a/symposion/teams/models.py +++ b/symposion/teams/models.py @@ -5,30 +5,36 @@ from django.db import models import reversion from django.contrib.auth.models import Permission, User +from django.utils.translation import ugettext_lazy as _ TEAM_ACCESS_CHOICES = [ - ("open", "open"), - ("application", "by application"), - ("invitation", "by invitation") + ("open", _("open")), + ("application", _("by application")), + ("invitation", _("by invitation")) ] class Team(models.Model): - slug = models.SlugField(unique=True) - name = models.CharField(max_length=100) - description = models.TextField(blank=True) - access = models.CharField(max_length=20, choices=TEAM_ACCESS_CHOICES) + slug = models.SlugField(unique=True, verbose_name=_("Slug")) + name = models.CharField(max_length=100, verbose_name=_("Name")) + description = models.TextField(blank=True, verbose_name=_("Description")) + access = models.CharField(max_length=20, choices=TEAM_ACCESS_CHOICES, + verbose_name=_("Access")) # member permissions - permissions = models.ManyToManyField(Permission, blank=True, related_name="member_teams") + permissions = models.ManyToManyField(Permission, blank=True, + related_name="member_teams", + verbose_name=_("Permissions")) # manager permissions manager_permissions = models.ManyToManyField(Permission, blank=True, - related_name="manager_teams") + related_name="manager_teams", + verbose_name=_("Manager permissions")) - created = models.DateTimeField(default=datetime.datetime.now, editable=False) + created = models.DateTimeField(default=datetime.datetime.now, + editable=False, verbose_name=_("Created")) @models.permalink def get_absolute_url(self): @@ -55,23 +61,32 @@ class Team(models.Model): def managers(self): return self.memberships.filter(state="manager") + class Meta: + verbose_name = _('Team') + verbose_name_plural = _('Teams') MEMBERSHIP_STATE_CHOICES = [ - ("applied", "applied"), - ("invited", "invited"), - ("declined", "declined"), - ("rejected", "rejected"), - ("member", "member"), - ("manager", "manager"), + ("applied", _("applied")), + ("invited", _("invited")), + ("declined", _("declined")), + ("rejected", _("rejected")), + ("member", _("member")), + ("manager", _("manager")), ] class Membership(models.Model): - user = models.ForeignKey(User, related_name="memberships") - team = models.ForeignKey(Team, related_name="memberships") - state = models.CharField(max_length=20, choices=MEMBERSHIP_STATE_CHOICES) - message = models.TextField(blank=True) + user = models.ForeignKey(User, related_name="memberships", + verbose_name=_("User")) + team = models.ForeignKey(Team, related_name="memberships", + verbose_name=_("Team")) + state = models.CharField(max_length=20, choices=MEMBERSHIP_STATE_CHOICES, + verbose_name=_("State")) + message = models.TextField(blank=True, verbose_name=_("Message")) + class Meta: + verbose_name = _("Membership") + verbose_name_plural = _("Memberships") reversion.register(Membership) diff --git a/symposion/teams/views.py b/symposion/teams/views.py index f45a0cba..a843be1c 100644 --- a/symposion/teams/views.py +++ b/symposion/teams/views.py @@ -5,6 +5,7 @@ from django.contrib.auth.decorators import login_required from django.contrib import messages from symposion.utils.mail import send_email +from django.utils.translation import ugettext_lazy as _ from symposion.teams.forms import TeamInvitationForm from symposion.teams.models import Team, Membership @@ -66,7 +67,7 @@ def team_detail(request, slug): if form.is_valid(): form.invite() send_email([form.user.email], "teams_user_invited", context={"team": team}) - messages.success(request, "Invitation created.") + messages.success(request, _("Invitation created.")) return redirect("team_detail", slug=slug) else: form = TeamInvitationForm(team=team) @@ -94,7 +95,7 @@ def team_join(request, slug): membership, created = Membership.objects.get_or_create(team=team, user=request.user) membership.state = "member" membership.save() - messages.success(request, "Joined team.") + messages.success(request, _("Joined team.")) return redirect("team_detail", slug=slug) else: return redirect("team_detail", slug=slug) @@ -110,7 +111,7 @@ def team_leave(request, slug): if can_leave(team, request.user) and request.method == "POST": membership = Membership.objects.get(team=team, user=request.user) membership.delete() - messages.success(request, "Left team.") + messages.success(request, _("Left team.")) return redirect("dashboard") else: return redirect("team_detail", slug=slug) @@ -132,7 +133,7 @@ def team_apply(request, slug): "team": team, "user": request.user }) - messages.success(request, "Applied to join team.") + messages.success(request, _("Applied to join team.")) return redirect("team_detail", slug=slug) else: return redirect("team_detail", slug=slug) @@ -148,7 +149,7 @@ def team_promote(request, pk): if membership.state == "member": membership.state = "manager" membership.save() - messages.success(request, "Promoted to manager.") + messages.success(request, _("Promoted to manager.")) return redirect("team_detail", slug=membership.team.slug) @@ -162,7 +163,7 @@ def team_demote(request, pk): if membership.state == "manager": membership.state = "member" membership.save() - messages.success(request, "Demoted from manager.") + messages.success(request, _("Demoted from manager.")) return redirect("team_detail", slug=membership.team.slug) @@ -176,7 +177,7 @@ def team_accept(request, pk): if membership.state == "applied": membership.state = "member" membership.save() - messages.success(request, "Accepted application.") + messages.success(request, _("Accepted application.")) return redirect("team_detail", slug=membership.team.slug) @@ -190,5 +191,5 @@ def team_reject(request, pk): if membership.state == "applied": membership.state = "rejected" membership.save() - messages.success(request, "Rejected application.") + messages.success(request, _("Rejected application.")) return redirect("team_detail", slug=membership.team.slug)