All posts for the month June, 2013

Django Translation Creating Locale Folders

As our huge project progresses we need to start thinking about some of the major features that our users would like to see.  The first is less of a feature and more of a necessity.  Our users are located all over the world and speak four different languages.  To accommodate all of these users we need to translate every bit of text on every page of our application for all of our users.  Luckily for us Django handles translation very nicely.  Read up on the Django translation here.

This post will only cover the template tag {% trans %}, more will come as we develop more of our translation setup.

Every template generated will need the tag {% load i18n %} at the top to have access to the trans tag.  From this point on any text string will need to be surrounded by the trans tag.  For example, my button has the code <button type="button">Home</button> and to use the translation I simply change it to <button type="button">{% trans "Home" %}</button>.  That string after the trans is going to be the id for the soon-to-be-created translation files.  This string can contain spaces and for our purposes we are going to make the id the default English string.  When a translation is not found it will display the id so in our case the correct English string will save time.

Once you’ve done all of that, and every string you want translated is contained in a trans tag, we need to generate a translation list for all of those strings.  Using Django 1.5.1 get into your application directory inside of your Django project.  Use the command makemessages -l <language code>.  This will generate a folder named the language code inside of a locale folder inside of your application.

OK, now for the reason I wanted to write this post.  I had a list of languages and was trying to test all of this out.  Things were working great for English and German using the language codes en-us and de but was failing for Chinese Simplified, zh-cn.  The reason is actually because though the language value is zh-cn do not use that language code when creating your message folder!  It actually wants to look into the folder zh_CN.  Language folders must be created with the language followed by and underscore and the version.  Since I am not using any translation files for English it doesn’t matter what I use but if I were to do English for the United States and English for the UK I would use the makemessages command and create the folders en_US and en_UK.

Just a quick note I wanted to make so that others, and myself, won’t fall into this misstep in the future.

Custom Django Admin Filter with Foreign Keys

During our massive redesign of our internal tools I wanted to make the Django admin page more friendly for us, the software engineers and admins.  Currently when they have problems or need things changed the easiest way to do that is through raw SQL and altering the database directly.  This is inconvenient and can lead to bad data.  Django, by design, abstracts that interaction and creates a great user-interface to interact with including filters and search options.

One of the strengths of this is you can define your own custom filters that will appear as normal filters on the UI.  Defining them is quite simple and you can check out the tutorial directly from Django(Search for DecadeBornListFilter).  I wanted to take the query a step further and have it look up items based on a characteristic of a parent object stored as a foreign key.  Using the double underscore (__) Django allows you to access data from that foriegn key in queries.  Following the tutorial I was able to quickyl make my query.

It worked great, except when the query was set to All.  When set to All it should display every object for that queryset because there are no parameters but since I was using foreign key fields I guess it didn’t like that and would display nothing.  When you selected specific filters the query worked but on the default nothing appeared.  I searched all over the Internet and found nothing about it so I made up my own solution.

My solution is to check whether or not there is a value.  On All there is no value and should return the queryset unchanged.  Before it would try to filter and return nothing.  This simple test made it so my admin page has a lot more functionality and was a simple fix that I couldn’t find written anywhere.  Hopefully this helps someone else through the odd behavior that can happen sometimes.