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?
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.
> 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.
> 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.
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
--
Gabriel Genellina
Fair enough.
>> 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()).
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.
Solution with decorators looks well, will try it in near future.
I will report here if I solve this problem.
> 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