dnscms: translate events app

This commit is contained in:
2026-05-19 21:25:28 +02:00
parent 696e6b8f11
commit 9ca9f5db11
5 changed files with 356 additions and 78 deletions
+11 -8
View File
@@ -2,6 +2,8 @@ from urllib.parse import urlencode
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext, gettext_lazy as _
from django.utils.translation import ngettext
from wagtail.admin.ui.tables import Column, DateColumn from wagtail.admin.ui.tables import Column, DateColumn
from wagtail.admin.ui.tables.pages import PageStatusColumn, PageTitleColumn from wagtail.admin.ui.tables.pages import PageStatusColumn, PageTitleColumn
from wagtail.admin.views.pages.choose_parent import ChooseParentView from wagtail.admin.views.pages.choose_parent import ChooseParentView
@@ -18,8 +20,9 @@ class EventDateColumn(Column):
return "" return ""
if len(occurrences) == 1: if len(occurrences) == 1:
local = timezone.localtime(occurrences[0].start) local = timezone.localtime(occurrences[0].start)
return local.strftime("%Y-%m-%d kl %H:%M") return local.strftime(gettext("%Y-%m-%d at %H:%M"))
return f"{len(occurrences)} forekomster" count = len(occurrences)
return ngettext("%(count)d occurrence", "%(count)d occurrences", count) % {"count": count}
class OrganizersColumn(Column): class OrganizersColumn(Column):
@@ -64,22 +67,22 @@ class EventPageListingViewSet(PageListingViewSet):
index_view_class = EventPageIndexView index_view_class = EventPageIndexView
choose_parent_view_class = EventChooseParentView choose_parent_view_class = EventChooseParentView
icon = "date" icon = "date"
menu_label = "Arrangementer" menu_label = _("Events")
menu_order = 1 menu_order = 1
add_to_admin_menu = True add_to_admin_menu = True
ordering = "-latest_revision_created_at" ordering = "-latest_revision_created_at"
columns = [ columns = [
PageTitleColumn("title", label="Tittel", sort_key="title", classname="title"), PageTitleColumn("title", label=_("Title"), sort_key="title", classname="title"),
EventDateColumn("event_date", label="Dato", width="13%"), EventDateColumn("event_date", label=_("Date"), width="13%"),
OrganizersColumn("organizers", label="Arrangører", width="12%"), OrganizersColumn("organizers", label=_("Organizers"), width="12%"),
DateColumn( DateColumn(
"latest_revision_created_at", "latest_revision_created_at",
label="Oppdatert", label=_("Updated"),
sort_key="latest_revision_created_at", sort_key="latest_revision_created_at",
width="10%", width="10%",
), ),
PageStatusColumn("status", label="Status", sort_key="live", width="10%"), PageStatusColumn("status", label=_("Status"), sort_key="live", width="10%"),
] ]
+70 -61
View File
@@ -75,11 +75,12 @@ class EventCategory(models.Model):
help_text=_("The name of the category as it will appear in URLs."), help_text=_("The name of the category as it will appear in URLs."),
) )
show_in_filters = models.BooleanField( show_in_filters = models.BooleanField(
default=False, help_text="Skal denne kategorien være mulig å filtrere på i programmet?" default=False,
help_text=_("Should this category be available as a filter in the event programme?"),
) )
PIG_CHOICES = [ PIG_CHOICES = [
("", "Ingen"), ("", _("None")),
] + ALL_PIGS ] + ALL_PIGS
pig = models.CharField( pig = models.CharField(
@@ -87,14 +88,14 @@ class EventCategory(models.Model):
choices=PIG_CHOICES, choices=PIG_CHOICES,
default="", default="",
blank=True, blank=True,
help_text="Standardgris for arrangementer av denne typen.", help_text=_("Default pig for events of this kind."),
) )
panels = [ panels = [
TitleFieldPanel("name"), TitleFieldPanel("name"),
FieldPanel("slug"), FieldPanel("slug"),
FieldPanel("show_in_filters"), FieldPanel("show_in_filters"),
FieldPanel("pig", heading="Gris"), FieldPanel("pig", heading=_("Pig")),
] ]
graphql_fields = [ graphql_fields = [
@@ -105,8 +106,8 @@ class EventCategory(models.Model):
] ]
class Meta: class Meta:
verbose_name = "Event category" verbose_name = _("event category")
verbose_name_plural = "Event categories" verbose_name_plural = _("event categories")
ordering = ["name"] ordering = ["name"]
def __str__(self): def __str__(self):
@@ -134,8 +135,8 @@ class EventOrganizerLink(Orderable):
return f"{self.organizer.name}" return f"{self.organizer.name}"
class Meta: class Meta:
verbose_name = "Arrangør" verbose_name = _("organizer")
verbose_name_plural = "Arrangører" verbose_name_plural = _("organizers")
constraints = [ constraints = [
UniqueConstraint( UniqueConstraint(
"event", "organizer", name="event_organizer_link_event_organizer_unique" "event", "organizer", name="event_organizer_link_event_organizer_unique"
@@ -163,13 +164,13 @@ class EventOrganizer(ClusterableModel):
blank=True, blank=True,
on_delete=models.PROTECT, on_delete=models.PROTECT,
related_name="organizers", related_name="organizers",
help_text="Om en samfundsforening eller et utvalg står bak, velg det her.", help_text=_("If a DNS association or committee is behind it, choose it here."),
) )
external_url = models.URLField( external_url = models.URLField(
blank=True, blank=True,
max_length=512, max_length=512,
help_text="Lenke til nettstedet til ekstern arrangør", help_text=_("Link to the external organizer's website"),
) )
panels = [ panels = [
@@ -178,15 +179,15 @@ class EventOrganizer(ClusterableModel):
FieldPanel( FieldPanel(
"association", "association",
widget=AssociationChooserWidget(linked_fields={"association": "#id_association"}), widget=AssociationChooserWidget(linked_fields={"association": "#id_association"}),
heading="Intern arrangør", heading=_("Internal organizer"),
), ),
MultiFieldPanel( MultiFieldPanel(
heading="Ekstern arrangør", heading=_("External organizer"),
children=[ children=[
FieldPanel( FieldPanel(
"external_url", "external_url",
heading="Nettsted", heading=_("Website"),
help_text="La denne stå tom om arrangøren finnes i lista over.", help_text=_("Leave this empty if the organizer exists in the list above."),
), ),
], ],
), ),
@@ -200,8 +201,8 @@ class EventOrganizer(ClusterableModel):
] ]
class Meta: class Meta:
verbose_name = "Event organizer" verbose_name = _("event organizer")
verbose_name_plural = "Event organizers" verbose_name_plural = _("event organizers")
ordering = ["name"] ordering = ["name"]
def __str__(self): def __str__(self):
@@ -234,19 +235,19 @@ class EventPage(HeadlessMixin, WPImportedPageMixin, Page):
blank=True, blank=True,
on_delete=models.SET_NULL, on_delete=models.SET_NULL,
related_name="+", related_name="+",
help_text=( help_text=_(
"Velg et bilde til bruk i programmet og andre visningsflater. " "Choose an image for use in the programme and other surfaces. "
"Bør være et bilde eller en illustrasjon uten tekst " "Should be a photo or an illustration without too much text "
" ikke gjenbruk et Facebook-cover ukritisk!" " don't reuse a Facebook cover uncritically!"
), ),
) )
subtitle = models.CharField( subtitle = models.CharField(
blank=True, blank=True,
max_length=128, max_length=128,
help_text=( help_text=_(
"En kort tekst som kommer rett under under tittelen. " "A short text that appears right below the title. "
"La denne gjerne stå tom om du fikk plass til det meste i tittelen." "Feel free to leave it empty if you fit most of it in the main title."
), ),
) )
lead = RichTextField(features=["italic", "link"], blank=True) lead = RichTextField(features=["italic", "link"], blank=True)
@@ -262,8 +263,8 @@ class EventPage(HeadlessMixin, WPImportedPageMixin, Page):
) )
PIG_CHOICES = [ PIG_CHOICES = [
("", "Ingen"), ("", _("None")),
("automatic", "Automatisk"), ("automatic", _("Automatic")),
] + ALL_PIGS ] + ALL_PIGS
pig = models.CharField( pig = models.CharField(
@@ -271,21 +272,21 @@ class EventPage(HeadlessMixin, WPImportedPageMixin, Page):
choices=PIG_CHOICES, choices=PIG_CHOICES,
default="automatic", default="automatic",
blank=True, blank=True,
help_text=( help_text=_(
"Grisen som henger på arrangementssiden. " "The pig that hangs out on the event page. "
"Automatisk fører til at en velges basert på arrangementets kategori." "Automatic causes one to be chosen based on the event's category."
), ),
) )
ticket_url = models.URLField( ticket_url = models.URLField(
blank=True, blank=True,
max_length=1024, max_length=1024,
help_text="Lenke direkte til billettkjøp, f.eks. TicketCo eller Ticketmaster", help_text=_("Direct link to ticket purchase, e.g. TicketCo, Billetto or Ticketmaster"),
) )
facebook_url = models.URLField( facebook_url = models.URLField(
blank=True, blank=True,
max_length=1024, max_length=1024,
help_text="Lenke direkte til arrangementet på Facebook", help_text=_("Direct link to the event on Facebook"),
) )
free = models.BooleanField(null=False, default=False) free = models.BooleanField(null=False, default=False)
@@ -294,63 +295,65 @@ class EventPage(HeadlessMixin, WPImportedPageMixin, Page):
price_member = models.CharField(max_length=32, blank=True) price_member = models.CharField(max_length=32, blank=True)
ticket_panels = [ ticket_panels = [
FieldPanel("free", heading="Gratis", help_text="Er dette arrangementet gratis for alle?"), FieldPanel("free", heading=_("Free"), help_text=_("Is this event free for everyone?")),
MultiFieldPanel( MultiFieldPanel(
children=[ children=[
FieldRowPanel( FieldRowPanel(
children=[ children=[
FieldPanel("price_regular", heading="Ordinær pris"), FieldPanel("price_regular", heading=_("Regular price")),
FieldPanel("price_student", heading="Pris for studenter"), FieldPanel("price_student", heading=_("Price for students")),
FieldPanel("price_member", heading="Pris for medlemmer av DNS"), FieldPanel("price_member", heading=_("Price for DNS members")),
], ],
help_text="", help_text="",
), ),
HelpPanel( HelpPanel(
content=mark_safe( content=mark_safe(
"Skriv <strong>0</strong> om gratis. " _(
"Tomt felt skjuler priskategorien. Om mulig, skriv kun tall." "Write <strong>0</strong> for free. "
"An empty field hides the price category. "
"If possible, write digits only."
)
) )
), ),
], ],
attrs={"id": "specific_pricing_panel"}, attrs={"id": "specific_pricing_panel"},
), ),
FieldPanel("ticket_url", heading="Billettkjøpslenke"), FieldPanel("ticket_url", heading=_("Ticket purchase link")),
] ]
content_panels = Page.content_panels + [ content_panels = Page.content_panels + [
FieldPanel("subtitle", heading="Undertittel"), FieldPanel("subtitle", heading=_("Subtitle")),
FieldPanel("featured_image"), FieldPanel("featured_image"),
FieldPanel("lead", heading="Ingress"), FieldPanel("lead", heading=_("Lead")),
FieldPanel("body"), FieldPanel("body"),
FieldPanel("categories", widget=forms.CheckboxSelectMultiple), FieldPanel("categories", widget=forms.CheckboxSelectMultiple),
MultiFieldPanel( MultiFieldPanel(
heading="Arrangører", heading=_("Organizers"),
children=[ children=[
HelpPanel( HelpPanel(
content=("Hvem står bak arrangementet?"), content=_("Who is behind the event?"),
), ),
MultipleChooserPanel( MultipleChooserPanel(
"organizer_links", chooser_field_name="organizer", label="Arrangør" "organizer_links", chooser_field_name="organizer", label=_("Organizer")
), ),
], ],
), ),
FieldPanel("pig", heading="Gris"), FieldPanel("pig", heading=_("Pig")),
FieldPanel( FieldPanel(
"facebook_url", "facebook_url",
heading="Facebook-lenke", heading=_("Facebook link"),
help_text="Lenke direkte til arrangementet på Facebook.", help_text=_("Direct link to the event on Facebook."),
), ),
MultiFieldPanel(heading="Priser og billettkjøp", children=ticket_panels), MultiFieldPanel(heading=_("Pricing and tickets"), children=ticket_panels),
MultiFieldPanel( MultiFieldPanel(
heading="Dato, tid og lokale", heading=_("Date, time and venue"),
children=[ children=[
HelpPanel( HelpPanel(
content=( content=_(
"Om arrangementet går over flere dager, " "If the event spans several days, add each day as a separate occurrence."
"legg inn hver dag som en egen forekomst."
), ),
), ),
InlinePanel("occurrences", min_num=1, label="Forekomst"), InlinePanel("occurrences", min_num=1, label=_("Occurrence")),
], ],
), ),
] ]
@@ -553,22 +556,24 @@ class EventOccurrence(Orderable):
blank=True, blank=True,
max_length=128, max_length=128,
help_text=mark_safe( help_text=mark_safe(
"Bruk denne <em>om ingen av lokalene som kan velges til venstre</em> passer. " _(
"F.eks. <em>Frederikkeplassen</em> eller <em>Sirkusteltet</em>." "Use this <em>if none of the venues that can be selected on the left</em> fit. "
"E.g. <em>Frederikkeplassen</em> or <em>Sirkusteltet</em>."
)
), ),
) )
panels = [ panels = [
FieldRowPanel( FieldRowPanel(
children=[ children=[
FieldPanel("start", heading="Start"), FieldPanel("start", heading=_("Start")),
FieldPanel("end", heading="Slutt"), FieldPanel("end", heading=_("End")),
], ],
), ),
FieldRowPanel( FieldRowPanel(
children=[ children=[
FieldPanel("venue", heading="Lokale"), FieldPanel("venue", heading=_("Venue")),
FieldPanel("venue_custom", heading="Lokale som fritekst"), FieldPanel("venue_custom", heading=_("Venue as free text")),
], ],
), ),
] ]
@@ -583,14 +588,18 @@ class EventOccurrence(Orderable):
def clean(self): def clean(self):
if self.venue and self.venue_custom: if self.venue and self.venue_custom:
raise ValidationError( raise ValidationError(
{"venue_custom": "Du kan ikke både velge et lokale og skrive noe i dette feltet."} {
"venue_custom": _(
"You can't both pick a venue and write something in this field."
)
}
) )
if not self.venue and not self.venue_custom: if not self.venue and not self.venue_custom:
raise ValidationError({"venue": "Lokale er påkrevd."}) raise ValidationError({"venue": _("Venue is required.")})
def __str__(self): def __str__(self):
return f"{self.start}--{self.end}" return f"{self.start}--{self.end}"
class Meta: class Meta:
verbose_name = "Forekomst" verbose_name = _("occurrence")
verbose_name_plural = "Forekomster" verbose_name_plural = _("occurrences")
+5 -4
View File
@@ -1,3 +1,4 @@
from django.utils.translation import gettext_lazy as _
from wagtail.admin.viewsets.chooser import ChooserViewSet from wagtail.admin.viewsets.chooser import ChooserViewSet
@@ -5,10 +6,10 @@ class EventOrganizerChooserViewSet(ChooserViewSet):
model = "events.EventOrganizer" model = "events.EventOrganizer"
icon = "group" icon = "group"
per_page = 30 per_page = 30
page_title = "Choose organizers" page_title = _("Choose organizers")
choose_one_text = "Choose an organizer" choose_one_text = _("Choose an organizer")
choose_another_text = "Choose another organizer" choose_another_text = _("Choose another organizer")
edit_item_text = "Edit this organizer" edit_item_text = _("Edit this organizer")
form_fields = ["name", "association", "external_url"] form_fields = ["name", "association", "external_url"]
Binary file not shown.
+270 -5
View File
@@ -7,14 +7,49 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dnscms\n" "Project-Id-Version: dnscms\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-05-19 20:44+0200\n" "POT-Creation-Date: 2026-05-19 21:17+0200\n"
"Language: nb\n" "Language: nb\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: events/models.py:73 events/models.py:155 #: events/admin.py:23
msgid "%Y-%m-%d at %H:%M"
msgstr "%Y-%m-%d kl %H:%M"
#: events/admin.py:25
#, python-format
msgid "%(count)d occurrence"
msgid_plural "%(count)d occurrences"
msgstr[0] "%(count)d forekomst"
msgstr[1] "%(count)d forekomster"
#: events/admin.py:70
msgid "Events"
msgstr "Arrangementer"
#: events/admin.py:76
msgid "Title"
msgstr "Tittel"
#: events/admin.py:77
msgid "Date"
msgstr "Dato"
#: events/admin.py:78 events/models.py:333
msgid "Organizers"
msgstr "Arrangører"
#: events/admin.py:81
msgid "Updated"
msgstr "Oppdatert"
#: events/admin.py:85
msgid "Status"
msgstr "Status"
#: events/models.py:73 events/models.py:156
msgid "slug" msgid "slug"
msgstr "permalenke" msgstr "permalenke"
@@ -22,18 +57,248 @@ msgstr "permalenke"
msgid "The name of the category as it will appear in URLs." msgid "The name of the category as it will appear in URLs."
msgstr "Navnet på kategorien slik det vil vises i URL-er." msgstr "Navnet på kategorien slik det vil vises i URL-er."
#: events/models.py:157 #: events/models.py:79
msgid "Should this category be available as a filter in the event programme?"
msgstr "Skal denne kategorien være mulig å filtrere på i programmet?"
#: events/models.py:83 events/models.py:266
msgid "None"
msgstr "Ingen"
#: events/models.py:91
msgid "Default pig for events of this kind."
msgstr "Standardgris for arrangementer av denne typen."
#: events/models.py:98 events/models.py:343
msgid "Pig"
msgstr "Gris"
#: events/models.py:109
msgid "event category"
msgstr "arrangementskategori"
#: events/models.py:110
msgid "event categories"
msgstr "arrangementskategorier"
#: events/models.py:138
msgid "organizer"
msgstr "arrangør"
#: events/models.py:139
msgid "organizers"
msgstr "arrangører"
#: events/models.py:158
msgid "The name of the organizer as it will appear in URLs." msgid "The name of the organizer as it will appear in URLs."
msgstr "Navnet på arrangøren slik det vil vises i URL-er." msgstr "Navnet på arrangøren slik det vil vises i URL-er."
#: events/models.py:395 #: events/models.py:167
msgid "If a DNS association or committee is behind it, choose it here."
msgstr "Om en samfundsforening eller -utvalg står bak, velg det her."
#: events/models.py:173
msgid "Link to the external organizer's website"
msgstr "Lenke til nettstedet til ekstern arrangør"
#: events/models.py:182
msgid "Internal organizer"
msgstr "Intern arrangør"
#: events/models.py:185
msgid "External organizer"
msgstr "Ekstern arrangør"
#: events/models.py:189
msgid "Website"
msgstr "Nettsted"
#: events/models.py:190
msgid "Leave this empty if the organizer exists in the list above."
msgstr "La denne stå tom om arrangøren finnes i lista over."
#: events/models.py:204
msgid "event organizer"
msgstr "arrangør"
#: events/models.py:205
msgid "event organizers"
msgstr "arrangører"
#: events/models.py:239
msgid ""
"Choose an image for use in the programme and other surfaces. Should be a "
"photo or an illustration without too much text don't reuse a Facebook "
"cover uncritically!"
msgstr ""
"Velg et bilde til bruk i programmet og andre visningsflater. Bør være et "
"bilde eller en illustrasjon uten for mye tekst ikke gjenbruk et Facebook-"
"cover ukritisk!"
#: events/models.py:249
msgid ""
"A short text that appears right below the title. Feel free to leave it empty "
"if you fit most of it in the main title."
msgstr ""
"En kort tekst som kommer rett under tittelen. La denne gjerne stå tom om du "
"fikk plass til det meste i hovedtittelen."
#: events/models.py:267
msgid "Automatic"
msgstr "Automatisk"
#: events/models.py:276
msgid ""
"The pig that hangs out on the event page. Automatic causes one to be chosen "
"based on the event's category."
msgstr ""
"Grisen som henger på arrangementssiden. Automatisk fører til at en velges "
"basert på arrangementets kategori."
#: events/models.py:284
msgid "Direct link to ticket purchase, e.g. TicketCo, Billetto or Ticketmaster"
msgstr "Lenke direkte til billettkjøp, f.eks. TicketCo, Billetto eller Ticketmaster"
#: events/models.py:289
msgid "Direct link to the event on Facebook"
msgstr "Lenke direkte til arrangementet på Facebook"
#: events/models.py:299
msgid "Free"
msgstr "Gratis"
#: events/models.py:299
msgid "Is this event free for everyone?"
msgstr "Er dette arrangementet gratis for alle?"
#: events/models.py:305
msgid "Regular price"
msgstr "Ordinær pris"
#: events/models.py:306
msgid "Price for students"
msgstr "Pris for studenter"
#: events/models.py:307
msgid "Price for DNS members"
msgstr "Pris for medlemmer av DNS"
#: events/models.py:314
msgid ""
"Write <strong>0</strong> for free. An empty field hides the price category. "
"If possible, write digits only."
msgstr ""
"Skriv <strong>0</strong> om gratis. Tomt felt skjuler priskategorien. Om "
"mulig, skriv kun tall."
#: events/models.py:323
msgid "Ticket purchase link"
msgstr "Billettkjøpslenke"
#: events/models.py:327
msgid "Subtitle"
msgstr "Undertittel"
#: events/models.py:329
msgid "Lead"
msgstr "Ingress"
#: events/models.py:336
msgid "Who is behind the event?"
msgstr "Hvem står bak arrangementet?"
#: events/models.py:339
msgid "Organizer"
msgstr "Arrangør"
#: events/models.py:346
msgid "Facebook link"
msgstr "Facebook-lenke"
#: events/models.py:347
msgid "Direct link to the event on Facebook."
msgstr "Lenke direkte til arrangementet på Facebook."
#: events/models.py:349
msgid "Pricing and tickets"
msgstr "Priser og billettkjøp"
#: events/models.py:351
msgid "Date, time and venue"
msgstr "Dato, tid og lokale"
#: events/models.py:355
msgid "If the event spans several days, add each day as a separate occurrence."
msgstr "Om arrangementet går over flere dager, legg inn hver dag som en egen forekomst."
#: events/models.py:359
msgid "Occurrence"
msgstr "Forekomst"
#: events/models.py:402
msgid "event" msgid "event"
msgstr "arrangement" msgstr "arrangement"
#: events/models.py:396 #: events/models.py:403
msgid "events" msgid "events"
msgstr "arrangementer" msgstr "arrangementer"
#: events/models.py:563
msgid ""
"Use this <em>if none of the venues that can be selected on the left</em> "
"fit. E.g. <em>Frederikkeplassen</em> or <em>Sirkusteltet</em>."
msgstr ""
"Bruk denne <em>om ingen av lokalene som kan velges til venstre</em> passer. "
"F.eks. <em>Frederikkeplassen</em> eller <em>Sirkusteltet</em>."
#: events/models.py:572
msgid "Start"
msgstr "Start"
#: events/models.py:573
msgid "End"
msgstr "Slutt"
#: events/models.py:578
msgid "Venue"
msgstr "Lokale"
#: events/models.py:579
msgid "Venue as free text"
msgstr "Lokale som fritekst"
#: events/models.py:596
msgid "You can't both pick a venue and write something in this field."
msgstr "Du kan ikke både velge et lokale og skrive noe i dette feltet."
#: events/models.py:601
msgid "Venue is required."
msgstr "Lokale er påkrevd."
#: events/models.py:607
msgid "occurrence"
msgstr "forekomst"
#: events/models.py:608
msgid "occurrences"
msgstr "forekomster"
#: events/views.py:9
msgid "Choose organizers"
msgstr "Velg arrangører"
#: events/views.py:10
msgid "Choose an organizer"
msgstr "Velg en arrangør"
#: events/views.py:11
msgid "Choose another organizer"
msgstr "Velg en annen arrangør"
#: events/views.py:12
msgid "Edit this organizer"
msgstr "Rediger denne arrangøren"
#: images/models.py:40 #: images/models.py:40
msgid "image" msgid "image"
msgstr "bilde" msgstr "bilde"