[Merge] lp:~songofacandy/bzr/i18n into lp:bzr

Alexander Belchenko bialix at ukr.net
Wed May 11 17:48:41 UTC 2011


Stephen J. Turnbull пишет:
> Alexander Belchenko writes:
> 
>  > I can add even more reasons against using _() in first place.
>  > 
>  > Function _() is just alias to some gettext method which is bound to 
>  > specific language at installing time.
> 
> That's false.  You can change languages at invocation time, and add
> new languages after installation.  You can even change languages on
> the fly (but this requires some extra effort from the application
> programmer, and I'm not sure whether it's possible with Python's
> gettext wrapper, I've only worked with previously I18N-ed programs in
> Python, not actually done the I18N myself -- all my experience with
> writing gettext code is in C).

I'm sorry, but if you talk about GNU gettext -- then let's talk about 
GNU gettext. Because standard gettext library in Python does not use 
standard GNU gettext libraries at all. In fact python gettext is pure 
python module and it's reimplementation of the gettext logic in python.

So, let's talk about python's gettext, not about GNU gettext here.

>  > So the usual practice for GUI applications
> 
> GUI apps like to treat the user as a single-celled organism, incapable
> of walking and chewing gum at the same time.  What else is new?  We
> can do better, past practice does not limit us.

OK, point taken.

> 
>  > is to install _() into global namespace leaving gettext to
>  > determine what language user wants to see and don't care about
>  > translations anymore.
> 
> gettext uses the POSIX locale API, which certainly sucks for many
> purposes, but for this application it ain't no biggee:
> 
>     setlocale(LC_MESSAGES, locale_of_choice)

> It's just not that hard.  Note that without a setlocale call, you
> won't get any translations anyway.

If you talk about GNU gettext then I agree.

But if you're trying to persuade me that python works the same way, 
you're wrong here. Python gettext does not require setlocale() call.
It just checks environment variables to determine the required language 
and that's all. You can test it yourself with the small python script 
I've attached to the mail. I've used mo files from qbzr, and i18n.py 
helper module from qbzr.

All you need is to run

python test.py

In my case (on both Windows and Linux/via Putty-ssh) I get russian 
translation of the string.

Here's the code of test.py for those who don't want to run that example.

import i18n
i18n.install()
print i18n.gettext("Show")

And I see russian translation:

bialix at cvv:~/i18n$ python test.py
Показать
bialix at cvv:~/i18n$ echo $LANG
ru_RU.KOI8-R

>  So you just add logic to pick up
> the user's preferred locale from a config file or query for it
> interactively or whatever, rather than delegating it to the
> environment with "setlocale(LC_ALL)".
> 
>  > 1) Function _() translates the strings to some language immediately. 
> [...]
>  > But  this is simply the wrong way for CLI like bzr, who wants to achieve 
>  > speed. Bzr wants to be lazy and don't do extra work until it's really 
>  > needed.
> 
> I don't understand what you mean by "immediately".  Of course the call
> to _() looks up and returns a string "immediately".  But gettext()
> doesn't do any work until called, which should be done at display
> time, and only for the strings to be displayed.  Where's the
> efficiency problem?

Because in Python everything on a module level has executed at the 
import time. So if you have in your module:

foo = gettext("FOO")

then this variable foo will be evaluated only once at the import time 
and you won't be able to change its translation ever.

> 
> Ie, in
> 
>     if need_m17n:
>         print _("Boy, do POSIX locale APIs suck!")
>     else
>         print _("POSIX locale APIs will do for most I18N usage.")
> 
> only one of the two strings will be looked up and translated on each
> pass through the block.  Or consider:

See my example above.

> 
>     # Dummy "marker" function for convenience of xgettext y amigos.
>     def N_(x): return x
> 
>     # No strings are translated, at nominal expense.
>     # It's probably possible to avoid the cost of the dummy function call.
>     look_ma_jit_translation = [ N_("one"),
>                                 N_("two"),
>                                 N_("three"),
>                                 N_("four"),
>                                 N_("five"),
>                                 N_("six") ]
> 
>     die = random.Random()
> 
>     # Two strings are translated.
>     print _("Result of die roll: "), 
>     print _(look_ma_jit_translation[die.randrange(0,6)])

I know about N_() and we're using it often enough in the QBzr/Explorer.

>  > 2) Function _() translate the strings to some language immediately.
>  > That will be VERY bad for tests which check output of bzr commands. 
>  > Output never will match until you have forced C locale before running tetst.
> 
> You should be doing that anyway, unless you're testing I18N features.
> Cf. the infamous non-bugs where en_US collates a-z as "aBbCc...Zz"
> ... screwing up all your regexps unless you use "[[:ugly:]]", er,
> "[[:lower:]]".

I'm not quite understand this, sorry. I've talked about bzr own internal 
blackbox tests which are checks the output of commands.

>  > 3) For QBzr/Explorer I've implemented support for user-defined language 
>  > of the UI, it's stored as language option in bazaar.conf.
> 
> It's easy to do that if you use gettext, simply by adjusting your
> setlocale() call.

Again, for python gettext I have another way.

>  > I can be wrong of course, and will be happy to hear the contra
>  > arguments.
> 
> I don't have time to dig into qbzr, but before you argue *against* a
> particular *implementation* you should find out what its capabilities
> are.  Everything you've mentioned so far is certainly possible with
> gettext().  *I've done it.*

I've read implementation of gettext.py enough times to understand (more 
or less) what it is doing under the hood. The code there is clear about 
how language and mo files are handled. Decoding of mo files is not very 
clear, and honestly I wasn't too much interested in that code.

> "Standards" == requirements are another matter:
> 
>  > So maybe my own standards a bit higher than in the other
>  > projects.
> 
> Your standards are higher, and that's why your projects do more than
> others do.  Not because they use gettext().
> 
> If your classes do a good job of I18N, and are compatible with tools
> that make it easy for translators to do their work (in practice, AFAIK
> this means generating .pot files for them), feel free to advocate
> them, of course.  I have no complaint against them, but they need to
> be at least as good as gettext.

They are built on top of python gettext, not GNU gettext.

-- 
All the dude wanted was his rug back
-------------- next part --------------
A non-text attachment was scrubbed...
Name: i18n.zip
Type: application/octet-stream
Size: 141810 bytes
Desc: not available
URL: <https://lists.ubuntu.com/archives/bazaar/attachments/20110511/b5bb56ef/attachment-0001.obj>


More information about the bazaar mailing list