Translation docstrings with gettext

S

sapient

Hello.

I found several discussions where this question was asked, but was not
answered.

Now I am creating Python-API for my application, and want create it
with translation support, including documentation strings for modules,
classes, methods etc.

It is simple to translate special-marked strings with gettext, but it
is problem with docstrings: if I mark them for translation like
_("""Some documentation string""") then it is not recognized as
docstring. If I omit _() markup, then string is not translated.

Script pygettext.py has key --docstrings that forces extraction
docstrings from module, so I suppose, that it must be way to use thier
translations.

---
I create small example, that demonstrates this problem:
Module with docstrings for translation:
{{{
#!python
"""testmodule docstring"""

class TestClass:
"""testmodule.TestClass docstring"""

def testClassMethod(self):
"""testmodule.TestClass.testClassMethod docstring"""
print _("Call TestClass.testClassMethod()")
}}}

Script for testing translation:
{{{
#!python
import os, gettext

localedir = os.path.join( os.path.dirname(__file__), "locale/" )

t = gettext.translation( 'testmodule', localedir=localedir,
languages=['ru'], codeset="cp1251" )
t.install()

import testmodule

help( testmodule )
testmodule.TestClass().testClassMethod()
}}}

It successfully translates _("Call TestClass.testClassMethod()") but
all docstrings stay untranslated.
Full example exists here:
https://docs.google.com/leaf?id=0B_rE4w6PFDYWODg5ZWJlYjMtYTQ5ZS00MTE3LTgxOWUtNjc5NzEzNzVjYzdh&hl=en

So, question is: How to translate docstrings in my example?
 
L

Lie Ryan

Hello.

I found several discussions where this question was asked, but was not
answered.

Why would you want to translate docstring? Docstring is meant for
developers not users. Maintaining a translated docstring is going to be
a maintenance hell and will either hampers your application's agility or
you will be left with obsolete docstrings in various languages you don't
know.

Anyway, my job is to answer questions, not question the economic
feasibility of your decision, so try this:

#!python
__doc__ = _("""testmodule docstring""")

class TestClass:
__doc__ = _("""testmodule.TestClass docstring""")

def testClassMethod(self):
__doc__ = _("""testmodule.TestClass.testClassMethod docstring""")
print _("Call TestClass.testClassMethod()")


If you want to avoid having the explicit assignment to __doc__, you can
also try using some metaclass or decorator magic to automatically wraps
docstring in a _() call.
 
S

sapient

Lie Ryan, thank you for your answer!
Why would you want to translate docstring? Docstring is meant for
developers not users.
I have mentioned that I want to provide API for existing image-
processing applicaion in Python.
In my case "developers" are "users".
Python provides great possibilities for documenting objects, I want to
use it for things such context help about API modules, classes,
methods, and want to do it in several languages.
Maintaining a translated docstring is going to be
a maintenance hell and will either hampers your application's agility or
you will be left with obsolete docstrings in various languages you don't
know.
You are right, there are problems here, but there are advantages too
(we are talking about API): developers can write documentation in
thier "cracked" English (like my), but professional translator can
correct it after with Poedit.
Anyway, my job is to answer questions, not question the economic
feasibility of your decision, so try this:

#!python
__doc__ = _("""testmodule docstring""")

class TestClass:
    __doc__ = _("""testmodule.TestClass docstring""")

    def testClassMethod(self):
        __doc__ = _("""testmodule.TestClass.testClassMethod docstring""")
        print _("Call TestClass.testClassMethod()")
Yes, I tried this method, but it does not work with methods and
functions, this line
__doc__ = _("""testmodule.TestClass.testClassMethod docstring""")
does nothing (There are not output in help()). Is it any way to assign
docstring for function explicity?
If you want to avoid having the explicit assignment to __doc__, you can
also try using some metaclass or decorator magic to automatically wraps
docstring in a _() call.

Yes, it will be better to avoid them, is it any existing tool/lib/
workaround that can do it?
I am follower of aproved, stable solutions, do not like to reinvent
the wheel.
 
G

Gabriel Genellina

Lie Ryan, thank you for your answer!
I have mentioned that I want to provide API for existing image-
processing applicaion in Python.
In my case "developers" are "users".
Python provides great possibilities for documenting objects, I want to
use it for things such context help about API modules, classes,
methods, and want to do it in several languages.

There were some efforts in this direction in the past (like the -D option
of pygettext; and there was even a .po file for Python itself and the
standard library) but they seem to have been abandoned long time ago.
Yes, it will be better to avoid them, is it any existing tool/lib/
workaround that can do it?

The turtle module contains a *very* basic translation mechanism; see
turtle.write_docstringdict() and read_docstringdict(). They don't use
gettext.
I am follower of aproved, stable solutions, do not like to reinvent
the wheel.

I'm afraid this particular kind of wheel has not been invented yet.
You may find more interested people in the i18n SIG - but it does not
appear to have a lot of traffic lately:
http://mail.python.org/mailman/listinfo/i18n-sig
 
L

Lie Ryan

Lie Ryan, thank you for your answer!
I have mentioned that I want to provide API for existing image-
processing applicaion in Python.
In my case "developers" are "users".
Python provides great possibilities for documenting objects, I want to
use it for things such context help about API modules, classes,
methods, and want to do it in several languages.

You are right, there are problems here, but there are advantages too
(we are talking about API): developers can write documentation in
thier "cracked" English (like my), but professional translator can
correct it after with Poedit.

Fair enough.
Yes, I tried this method, but it does not work with methods and
functions, this line
does nothing (There are not output in help()).

Ah, my bad; I didn't notice.
Is it any way to assign
docstring for function explicity?

Yes there is, you will need to reassign the (translated) __doc__ from
*outside* the function definition, a decorator will provide nice
wrapper. This works:

__doc__ = _("""testmodule docstring""")__doc__ = _("""testmodule
docstring""")

def tdoc(obj):
obj.__doc__ = _(obj.__doc__)
return obj

@tdoc
class TestClass:
"""testmodule.TestClass docstring"""
@tdoc
def testClassMethod(self):
"""testmodule.TestClass.testClassMethod docstring"""
print _("Call TestClass.testClassMethod()")

# the decorator is equivalent to:
# def testClassMethod(self):
# print _("Call TestClass.testClassMethod()")
# testClassMethod.__doc__ = _(testClassMethod.__doc__)


as I said, you probably will want to use some metaclass magic to
automatically apply tdoc to all classes and methods. If just mandating
that tdoc must decorate everything works for you, then great.
 
S

sapient

Thank you for your help.

Solution with decorators looks well, will try it in near future.
I will report here if I solve this problem.
 
P

Peter Otten

sapient said:
I found several discussions where this question was asked, but was not
answered.

Now I am creating Python-API for my application, and want create it
with translation support, including documentation strings for modules,
classes, methods etc.

It is simple to translate special-marked strings with gettext, but it
is problem with docstrings: if I mark them for translation like
_("""Some documentation string""") then it is not recognized as
docstring. If I omit _() markup, then string is not translated.

Script pygettext.py has key --docstrings that forces extraction
docstrings from module, so I suppose, that it must be way to use thier
translations.
So, question is: How to translate docstrings in my example?

You could leave the docstrings alone and monkey-patch inspect.getdoc() to do
the translation when help() is invoked:

#! /usr/bin/python2.6
# -*- coding: utf-8 -*-
import os, gettext

localedir = os.path.join( os.path.dirname(__file__), "locale/" )

t = gettext.translation( 'testmodule', localedir=localedir,
languages=['ru'], codeset="utf-8" )
t.install()

import testmodule

import inspect
def getdoc(object):
try:
doc = object.__doc__
except AttributeError:
return None
if not isinstance(doc, basestring):
return None

return inspect.cleandoc(_(doc))

inspect.getdoc = getdoc


help( testmodule )
testmodule.TestClass().testClassMethod()

Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,708
Messages
2,569,347
Members
44,652
Latest member
DyanErliki

Latest Threads

Top