Changes between Version 4 and Version 5 of Dev/i18n
- Timestamp:
- 07/28/11 12:19:54 (22 months ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Dev/i18n
v4 v5 5 5 == Writing i18n-aware code == 6 6 7 === The basics === 8 9 The basic tool in code i18n is `_()`. In indico, this function is available by default ('''no need to import!''') everywhere. So, the code: 10 11 {{{ 12 #!python 13 print _('Fetch the cow') 14 }}} 15 16 would be displayed as: 17 18 {{{ 19 Fetchez la vache 20 }}} 21 22 considering that we had a [wikipedia:Franglais Franglais] dictonary loaded. A dictionary is just a map that associates an "original string" with a "translated string". Every language will have its own dictionary, that is application dependent and had to be loaded beforehand (we will see more below). 23 24 Anyone who has done (web) interface programming before can immediately see some tricky use cases that would not work. For example: 25 26 {{{ 27 print _('Fetch %d cows' % number) 28 }}} 29 30 would imply that we have an infinite dictionary. Of course the fix is easy: 31 32 {{{ 33 print _('Fetch %d cows') % number 34 }}} 35 36 And both Babel and `msgfmt` can handle format strings, and even warn you whenever the translation does not include the correct characters, etc. 37 38 === Plurals === 39 40 However, this is not enough. Suppose that 'number = 1'. How do we handle that? We could add an `if` expression and a single translation for "Fetch 1 cow". However, there is an easier/cleaner way: 41 42 {{{ 43 from indico.util.i18n import ungettext # unicode ngettext 44 45 print ungettext("Fetch %s cow", "Fetch %s cows", number) % number 46 47 }}} 48 49 You might be asking why we do not simply do: 50 51 {{{ 52 print "%s %s %s" % (_("Fetch"), number, ungettext("cow", "cows", number)) 53 }}} 54 55 The answer is: we should '''never''' make any assumptions about the order of word in a sentence. If in English it is generally true that the verb comes before the object, for other languages that may not be right. That's why it's better to spend some more characters and translate the whole sentence - like this, translators won't see themselves limited by the assumptions you've done in your code. 56 57 === Dates/Times === 58 59 === Others === 60 61 === Common mistakes === 7 62 It's very hard to write/maintain an application that is 100% internationalized, since this requires a great deal of coordination not only with the translators, but between developers as well. Not only people usually forget to properly internationalize strings, but also when they remember to do so they choose to do it at the wrong place. Here are some examples of some good/bad practices. 8 63 … … 27 82 Why is this wrong? Class attributes are initialized only once, '''at module load time'''. So, since modules are normally only loaded once '''per process''', a French user that is using this app will ''theoretically'' (see paragraph below) get the same translation as a Japanese one. The '''right way''' to do so would be delaying translation till the template is rendered: we could have a dictionary of "English" strings and then just call `_()` from the piece of template (or other i18n-safe code) that calls `getUserType`. 28 83 29 Fortunately our current i18n code supports Lazy translation(meaning that it replaces the result string with a proxy object that will only execute the translation when it is asked for its string value), and the situation above would not be problematic. However, it '''not at all good practice''' and should be '''avoided'''.84 Fortunately our current i18n code supports (thanks to Babel) "lazy translation" (meaning that it replaces the result string with a proxy object that will only execute the translation when it is asked for its string value), and the situation above would not be problematic. However, it '''not at all good practice''' and should be '''avoided'''. 30 85 31 86 Another classic mistake is: … … 44 99 45 100 This one should be easier to spot, if you consider that `Persistent` objects are stored in the database. By translating `position`, we get it in the language that was in use at the time of object creation. The right way to do it is, once again, to translate "as late as possible". 101 102 103 == Managing dictionaries ==
