20111111

browser-specific UI language

Started support for user-specific language selection. The basic trick is to add Django’s LocaleMiddleware to MIDDLEWARE_CLASSES as described in How Django discovers language preference. This makes Django ask the user’s browser’s language preferences and set request.LANGUAGE_CODE.

Until now I thought that was enough… but it turns out that there are a few places where I need to adapt Lino…

First and most evident was that the server must generate not only one file lino.js at startup, but one for each language. That wasn’t too difficult.

Next problem is that Choice Lists trigger translation when filling their choices list.

That’s subtile! Check-in 20111111 before touching this problem.

After more than 2 hours of my evening I found the solution, which is only one line in lino.utils.choicelists.ChoiceList.display_text(): Before:

@classmethod
def display_text(cls,bc):
    return unicode(bc)

After:

from django.utils.functional import lazy

@classmethod
def display_text(cls,bc):
    return lazy(unicode,unicode)(bc)

That is, this method now returns a Promise of a call to unicode() and not already the result of a call to unicode().

And another line of code had to change, the __unicode__() method of lino.modlib.properties.PropertyOccurence must explicitly call unicode on that Promise.

As a side-effect, some unit tests needed to change because we use now LocaleMiddleware: we cannot any longer use lino.utils.babel.set_language() to select the response language, instead we must pass a HTTP_ACCEPT_LANGUAGE keyword to Django’s TestCase.client.get() function. The unit tests would break again if for some reason we’d remove LocaleMiddleware again.

Check-in 20111111b.

Another problem was that many labels were converted to unicode in ext_elems when creating the UI widgets. Solved in check-in 20111111c.

And a last problem (for today) was that in lino.modlib.countries.models I used ugettext and not ugettext_lazy for marking translatable strings.

Check-in 20111111d.

Other changes

While researching for the above solution I did a few internal optimizations:

  • The few_countries fixture now adds multilingual country names
  • New function lino.utils.codetime() used by lino.ui.extjs3.ext_ui.ExtUI.build_lino_js() to avoid recreating the lino.js files on each server restart. Seems to work, but there may be unexpected surprises…

Closing the top-level window

Wenn man das “oberste” Fenster schließt, sieht man jetzt nicht mehr wie gewohnt die Erinnerungen, sondern nur eine weiße Fläche. Man muss explizit auf “Startseite” klicken, um die Erinnerungen anzuzeigen. Besser wäre, wenn das oberste Fenster gar nicht erst einen Close-Button hätte.