I am using Django's i18n mechanisms to translate an app in several languages (Django 1.11).
Situation
I have a Model with a Field takings choices:
from django.utils.translation import ugettext_lazy as _
class Offer(models.Model):
WEEK = 'week'
MONTH = 'month'
YEAR = 'year'
DURATION_CHOICES = (
(WEEK, _('week'),
(MONTH, _('month'),
(YEAR, _('year'),
)
duration = models.CharField(choices=DURATION_CHOICES, max_length=5, blank=True, null=True, \
verbose_name=_("offer's duration"), help_text=_("Duration for which an offer, once subscribed, stays valid")
If I want to display this field in a template:
{{ counter }} remaining {{ offer.get_duration_display}}{{ counter|pluralize}}
Where counter
is an integer, offer
an Offer object. Here it works well enough because plural forms for ('week', 'month', 'year') are ('weeks', 'months', 'years'), same words with an 's' ending.
Problem
Now let's say I want to translate my app to French. This gets tricky, because the corresponding translations are ('semaine', 'mois', 'année') and their plural forms are ('semaines', 'mois', 'années'): the translation for 'month' is the same in singular and plural forms.
So what I would like to do is defining custom plural forms for each choice in the duration Field.
Sure enough, I could use if
statements, but this is not elegant nor practical. So I tried to find a DRY solution.
What I tried
You can easily give a plural form to a Model's name with verbose_name_plural, but I didn't find anything for Fields or choices.
So I tried to use the ungettext_lazy
function, like this:
(Edit: so, it appears one must not choose a custom name other than _ for gettext and consorts)
from django.utils.translation import ungettext_lazy as _
class Offer(models.Model):
WEEK = 'week'
MONTH = 'month'
YEAR = 'year'
DURATION_CHOICES = (
(WEEK, _('week', 'weeks')),
(MONTH, _('month', 'months')),
(YEAR, _('year', 'years')),
)
django-admin makemessages -l fr
does output those strings in the *.po file, but it doesn't work: in English, the get_duration_display()
returns an empty string.
Anyway, I don't know how I would use it, because you can't pass parameters to the get_FOO_display
function...
Question
Would there be any way to do it? (without having to use conditional statements in my views or templates).
Do I have to override existing functions or code new ones?
I found this question (Django: override get_FOO_display()), where the answer points in an interesting direction. But this is quite tricky and I'm honestly a bit in over my head.
Can you think of another way to achieve this? Maybe an existing plugin?