Merge branch 'i18n-all' of https://github.com/miurahr/symposion into miurahr-i18n-all

Conflicts:
	symposion/boxes/models.py
	symposion/conference/models.py
	symposion/schedule/models.py
	symposion/speakers/models.py
	symposion/sponsorship/admin.py
	symposion/sponsorship/models.py
	symposion/teams/models.py
This commit is contained in:
Patrick Altman 2015-09-08 15:07:24 -05:00
commit 67433cacb4
25 changed files with 340 additions and 241 deletions

View file

@ -2,6 +2,7 @@ from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
import reversion
@ -11,17 +12,17 @@ from markitup.fields import MarkupField
@python_2_unicode_compatible
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 __str__(self):
return self.label
class Meta:
verbose_name_plural = "boxes"
verbose_name = _("Box")
verbose_name_plural = _("Boxes")
reversion.register(Box)

View file

@ -40,6 +40,10 @@ class Page(models.Model):
def __str__(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])

View file

@ -1,8 +1,9 @@
from __future__ import unicode_literals
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")

View file

@ -15,11 +15,11 @@ 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(blank=True, verbose_name=_("timezone"))
@ -53,14 +53,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 __str__(self):
return "%s %s" % (self.conference, self.name)

View file

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

View file

@ -2,10 +2,11 @@ from __future__ import unicode_literals
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
@ -32,5 +33,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

View file

@ -1,8 +1,9 @@
from __future__ import unicode_literals
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")

View file

@ -1,6 +1,7 @@
from __future__ import unicode_literals
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
@ -12,7 +13,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):
@ -27,7 +28,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

View file

@ -34,12 +34,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):
@ -71,10 +71,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 __str__(self):
return self.name
@ -85,9 +85,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
@ -101,6 +101,7 @@ class ProposalBase(models.Model):
"target='_blank'>Markdown</a>.")
)
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 "
@ -110,8 +111,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:
@ -120,8 +122,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
@ -179,12 +182,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 __str__(self):
if self.status is self.SPEAKING_STATUS_PENDING:
@ -203,14 +208,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",

View file

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

View file

@ -1,8 +1,9 @@
from __future__ import unicode_literals
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")

View file

@ -1,5 +1,6 @@
from __future__ import unicode_literals
from django import forms
from django.utils.translation import ugettext_lazy as _
from markitup.widgets import MarkItUpWidget
@ -36,6 +37,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.")
)

View file

@ -8,6 +8,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
@ -32,10 +33,10 @@ class Votes(object):
MINUS_ONE = "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()
@ -48,18 +49,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):
@ -93,27 +94,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:
@ -181,20 +184,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 {
@ -206,25 +215,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):
@ -280,35 +289,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():

View file

@ -1,10 +1,12 @@
from __future__ import unicode_literals
import datetime
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.models import User
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from markitup.fields import MarkupField
@ -16,22 +18,24 @@ from symposion.speakers.models import Speaker
@python_2_unicode_compatible
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 __str__(self):
return "%s Schedule" % self.section
class Meta:
ordering = ["section"]
verbose_name = _('Schedule')
verbose_name_plural = _('Schedules')
@python_2_unicode_compatible
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 __str__(self):
return "%s" % self.date
@ -39,18 +43,24 @@ class Day(models.Model):
class Meta:
unique_together = [("schedule", "date")]
ordering = ["date"]
verbose_name = _("date")
verbose_name_plural = _("dates")
@python_2_unicode_compatible
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 __str__(self):
return self.name
class Meta:
verbose_name = _("Room")
verbose_name_plural = _("Rooms")
@python_2_unicode_compatible
class SlotKind(models.Model):
@ -59,21 +69,25 @@ 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 __str__(self):
return self.label
class Meta:
verbose_name = _("Slot kind")
verbose_name_plural = _("Slot kinds")
@python_2_unicode_compatible
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):
"""
@ -137,6 +151,8 @@ class Slot(models.Model):
class Meta:
ordering = ["day", "start", "end"]
verbose_name = _("slot")
verbose_name_plural = _("slots")
@python_2_unicode_compatible
@ -145,8 +161,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 __str__(self):
return "%s %s" % (self.room, self.slot)
@ -154,21 +170,23 @@ class SlotRoom(models.Model):
class Meta:
unique_together = [("slot", "room")]
ordering = ["slot", "room__order"]
verbose_name = _("Slot room")
verbose_name_plural = _("Slot rooms")
@python_2_unicode_compatible
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):
@ -191,13 +209,15 @@ class Presentation(models.Model):
class Meta:
ordering = ["slot"]
verbose_name = _("presentation")
verbose_name_plural = _("presentations")
@python_2_unicode_compatible
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")
@ -227,6 +247,10 @@ class Session(models.Model):
)
return ""
class Meta:
verbose_name = _("Session")
verbose_name_plural = _("Sessions")
@python_2_unicode_compatible
class SessionRole(models.Model):
@ -235,19 +259,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 __str__(self):
return "%s %s: %s" % (self.user, self.session,

View file

@ -1,8 +1,9 @@
from __future__ import unicode_literals
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")

View file

@ -1,9 +1,11 @@
from __future__ import unicode_literals
import datetime
from django.utils.encoding import python_2_unicode_compatible
from django.db import models
import datetime
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
@ -18,24 +20,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 "
"<a href='http://warpedvisions.org/projects/"
"markdown-cheat-sheet/target='_blank'>"
"Markdown</a>."))
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 "
"<a href='http://warpedvisions.org/projects/"
"markdown-cheat-sheet/target='_blank'>"
"Markdown</a>."), 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 __str__(self):
if self.user:

View file

@ -6,6 +6,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
@ -34,7 +35,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()})
@ -62,7 +63,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()})
@ -89,8 +90,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():

View file

@ -69,9 +69,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

View file

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

View file

@ -3,6 +3,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
@ -65,7 +66,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":

View file

@ -48,16 +48,16 @@ BENEFITS = [
@python_2_unicode_compatible
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 __str__(self):
return "%s %s" % (self.conference, self.name)
@ -69,22 +69,22 @@ class SponsorLevel(models.Model):
@python_2_unicode_compatible
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"))
# Whether things are complete
# True = complete, False = incomplate, Null = n/a for this sponsor level
@ -99,8 +99,8 @@ class Sponsor(models.Model):
return self.name
class Meta:
verbose_name = _("sponsor")
verbose_name_plural = _("sponsors")
verbose_name = _("Sponsor")
verbose_name_plural = _("Sponsors")
ordering = ['name']
def save(self, *args, **kwargs):
@ -213,12 +213,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 = [
@ -231,10 +231,10 @@ CONTENT_TYPE_CHOICES = [
@python_2_unicode_compatible
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")
@ -245,15 +245,17 @@ class Benefit(models.Model):
@python_2_unicode_compatible
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 __str__(self):
return "%s - %s" % (self.level, self.benefit)
@ -262,18 +264,18 @@ class BenefitLevel(models.Model):
@python_2_unicode_compatible
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")
# Whether any assets required from the sponsor have been provided
# (e.g. a logo file for a Web logo benefit).
@ -281,6 +283,8 @@ class SponsorBenefit(models.Model):
class Meta:
ordering = ["-active"]
verbose_name = _("Sponsor benefit")
verbose_name_plural = _("Sponsor benefits")
def __str__(self):
return "%s - %s (%s)" % (self.sponsor, self.benefit, self.benefit_type)
@ -296,8 +300,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):
"""

View file

@ -7,16 +7,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, \
@ -91,7 +89,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:

View file

@ -3,6 +3,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
@ -11,8 +12,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")
@ -23,7 +25,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)
@ -31,16 +33,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 <b>%s</b> found on this conference "
"site" % escape(email)))
mark_safe(_("no account with email address <b>%s</b> 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

View file

@ -1,37 +1,44 @@
from __future__ import unicode_literals
import datetime
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import Permission, User
import reversion
from django.contrib.auth.models import Permission, User
from django.utils.encoding import python_2_unicode_compatible
TEAM_ACCESS_CHOICES = [
("open", "open"),
("application", "by application"),
("invitation", "by invitation")
("open", _("open")),
("application", _("by application")),
("invitation", _("by invitation"))
]
@python_2_unicode_compatible
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):
@ -58,23 +65,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)

View file

@ -6,6 +6,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
@ -67,7 +68,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)
@ -95,7 +96,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)
@ -111,7 +112,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)
@ -133,7 +134,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)
@ -149,7 +150,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)
@ -163,7 +164,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)
@ -177,7 +178,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)
@ -191,5 +192,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)