views:

534

answers:

2

Im a coding a library inluding textual feedback that I need to translate.

I put the following lines in a _config.py module that I import everywhere in my app :

import gettext, os, sys
pathname = os.path.dirname(sys.argv[0])
localdir = os.path.abspath(pathname) + "/locale"
gettext.install("messages", localdir)

I have the *.mo files in ./locale/lang_LANG/LC_MESSAGES and I apply the _() function to all the strings that need to be translated.

Now I just added a feature for the user, supposedly a programmer, to be able to create his own messages. I don't want him to care about the underlying implementation, so I want him to be apple to make it something straightforward like :

lib_object.message = "My message"

I used properties to make it clean, but what if my user whats to translate his own code (that uses mine) and does something like :

import gettext, os, sys
pathname = os.path.dirname(sys.argv[0])
localdir = os.path.abspath(pathname) + "/locale"
gettext.install("user_app", localdir)

lib_object.message = _("My message")

Is it a problem ? What can I do to avoid troubles without bothering my user ?

+1  A: 

You can only gettext.install() once. In general it's useless for library work -- gettext.install() will only do the right thing if the module calling it is in charge of the whole program, since it will only provide you with one catalog to load from. Library code should do something akin to what Mailman does: have their own wrapper for gettext() that passes the right arguments for this module, then imports that as '_' in each module that wants to use it.

Thomas Wouters
Do you know where I can find a snippet to do that ? E.G : where can I find the mail man source code ?
e-satis
+1  A: 

You can use the class based gettext api to isolate message catalogs. This is also what is recommended in the python gettext documentation.

The drawback is that you, or the other dev, will have to use the gettext method or define the _() method in the local scope, bound to the specific gettext class. An example of a class with its own string catalog:

import gettext

class MyClass(object):
    def __init__(self, locale_for_instance):
        self.lang = gettext.translation("appname", localedir, \
                                         locale=locale_for_instance)

    def some_method(self, arg):
        return self.lang.gettext("You called some method")

    def other_method(self, arg): # does the same thing
        _ = self.lang.gettext
        return _("You called some method")

You could stick the code for adding the _() in a decorator, so all the methods that need it is prefixed with something like @with_local_gettext

(Note, I've not tested the above could but It Should Work Just Fine(tm) )

If the goal is to not bother your user (and he's not very good) I guess you could use the class based approach in your code and let the user use the global one.

runeh