localdates is a django app that brings local date presentation to django, by providing custom date filters that can use local-flavored format strings.

Reasoning

I'm Greek, and the greek language is a lot more complicated than english. There are genders and cases and more stuff that change the suffixes of the words, depending on the use. This is very annoying when trying to create a multilingual site, or when using a multilingual framework like Django. As Malcolm Tredinnick , one of Django's lead developers has put it:

(1) The fundamental reason this (date formats) is a problem at all is because we are attempting to construct grammatical sentences out of short fragments. A guiding principle in creating translatable strings is to create complete strings as often as possible because constructing sentences from fragments is very locale specific.

From: the relevant discussion, continued from ticket 4147

One of the most visible aspects of this problem is, as you may have guessed, date presentation. Date is a very common function in most sites, and having it appear correctly is a major issue. Up to now, if you wanted a date to look correct in Greek, the only option was to use an all-numeric format like this: 2/8/1982 (that's my birthday, but I bet you aren't sure if I was born on August 2 or February 8. More on that later on.)

The problems

I've described the one problem above -- mainly, the peculiarities of grammar and syntax present in many languages. I've hinted about the second problem in the last paragraph: The way people around the earth prefer to structure a date phrase. Greeks (and Germans, and British AFAIK) prefer to write dates like DD/MM/YYYY, while folks from the states prefer MM/DD/YYYY. There are lots of different formats, which is my point: I'm not supposed to know them all!.

Django comes with translations for many languages, so if I want to display the admin application in, say, Portuguese, I can, because the nice django folks from Portugal have translated it. But the dates will still look wrong, because you can't translate a date format string.

Actually, I tell a lie. You can do that. In django.utils.translate_real, you can find some interesting code that defines some default formats. I only found that today, I'm not sure when it got in or how should I use it.

But anyway, here's my take:

  1. Most of the time, we just use standard forms of date presentation, like formal date, abbreviated date, numeric date and so on.
  2. Developers don't know what the correct date presentation for each locale is - the translators know that.
  3. Django's dateformat can't handle all the peculiarities of international date formats, because of point (2) - the developers can't be expected to know that.

Ergo, we need a way to let translators specify their date formats and implement their language's way of displaying them. Here is where localdates comes in.

Introducing localdates

Localdates, for the end user (a developer who likes his nice dates) is just a replacement for the date filter, called ldate:

I was born on {{my_birthday|ldate:"{FULL_DATE}"}}!

Or maybe:

Γεννήθηκα στις {{my_birthday|ldate:"j {Fp}, Y"}

Update: You can also create your own translatable date strings, like this:

My birthday is on {{my_birthday|ldate:"{_(MY_BIRTHDAY)}"}

You have to put manually this msgid (MY_BIRTHDAY) in the django.po file of your project. The ldate filter will handle the translation.

You'll notice how one can specify a standard string ({FULL_DATE}), and it works out automagically. You'll also notice how there is a new format string that is enclosed in brackets ({Fp}). Here is where the translators come in.

New format strings

These new format strings are language-specific. The translators decide what their names will be, and how will they work. Developers who create sites in one language can use them freely, while others that create multilingual sites should use the standard strings.

Localdates looks in django.contrib.localflavor to find a module named dateformat, that has a class named LocalDateFormat. Within this class are two-letter functions that both define and implement the special format strings. Example:

from django.contrib.localdates.local_dateformat import DefaultLocalDateFormat  
from local_dates import MONTHS_POS, MONTHS_DIR

class LocalDateFormat(DefaultLocalDateFormat):

    def Fp(self):
        return MONTHS_POS[self.data.month]

    def Fd(self):
        return MONTHS_DIR[self.data.month]

In this case, Fp returns a month in its posessive form and Fd returns a month in its accusative form.

Request for comments

I presume that most of the functionality between languages will be the same. It is my goal to put that in a common place so that after the initial development we won't have duplication. So please please anyone that uses django that has the same issues as I do, please give the localdates a try.

You can download the source from:

http://code.google.com/p/django-localdates/source

There are complete usage instructions here:

http://code.google.com/p/django-localdates/wiki/Usage

Conclusion

This is a work in progress. I'd like some feedback from users that use other languages. Also, please forgive me for using django.contrib.localdates for the name. This app fits nicely in the contrib section of Django and I like it placed there, as the localflavored dateformats can all have a common base. It'd be great to be included in the Django trunk, but I'm not responsible for that.

July 17, 2007, 2:18 p.m. More (870 words) 6 comments Feed
Previous entry: Creating a portable development environment
Next entry: New MacBook, new hand...

Comments

1

Comment by Bill , 7 years, 5 months ago :

Minor point: in the first paragraph in 'The problems' section, you say British folk prefer dates in the MM/DD/YYYY format. Standard British English actually follows Greek and German style, DD/MM/YYYY.

2

Comment by Jacob Kaplan-Moss , 7 years, 5 months ago :

Ooh, this is interesting -- looks like it could be quite useful.

One quick question: did you consider trying to do this using the DATE_FORMAT setting (http://www.djangoproject.com/document...) and friends? Why/why not?

3

Comment by Orestis Markou , 7 years, 5 months ago :

Bill: Whoops! I'll fix that.

Jacob: I've seen this setting a bit late. It looks like it could be used, but I think it needs to be expanded. Maybe I could just fall back to it if there are no other options. I can't see any way that DATE_FORMAT is accessible from a template filter.

My array of date options is wider than the DATE_FORMAT setting, so I think it'll be more flexible.

I'd like comments for the django lead developers on the quality of code - if this can be included in the django trunk it'd be great. I've pinged Malcolm who I think is responsible for the i18n features.

4

Comment by Orestis Markou , 7 years, 5 months ago :

I've updated the code with support for translatable date strings, in the format:

{_(MY_DATE_STRING)}

for now, you have to directly put the msgid in the django.po file, as I don't know how to plug into make-messages.py functionality. It's not a big deal.

5

Comment by zyegfryed , 7 years, 5 months ago :

Hi,
A new Python projet, Babel (http://babel.edgewall.org/), dealing with Date Formatting (http://babel.edgewall.org/wiki/Docume...) is announcing (http://www.cmlenz.net/blog/2007/06/an...).
Hope it helps.
Seb

Via (http://simonwillison.net/2007/Jul/20/...)

6

Comment by Orestis Markou , 7 years, 5 months ago :

zyegfryed: That seems very nice. I wonder if it is easy to plug it into Django. I'll take a look to see if my work is now obsolete (I don't think so)...


This post is older than 30 days and comments have been turned off.