1

How can I translate Python's argparse module strings?

For example, when you display the help, it says "usage: ", string that is translatable but I don't know how to do it in my program.

This is the source code part of argparse.py:

def _format_usage(self, usage, actions, groups, prefix):
        if prefix is None:
            prefix = _('usage: ')

I couldn't trace the way to set this prefix, I think this is internal.

I don't want to have to append a .mo file to somewhere in the system. Ideally the translation should live in my program directory, or better in the source code.

Any help would be much appreciated.

JorgeeFG
  • 5,651
  • 12
  • 59
  • 92

2 Answers2

2

Running the following:

import argparse

class MyHelpFormatter(argparse.HelpFormatter):
    def __init__(self, *args, **kwargs):
        super(MyHelpFormatter, self).__init__(*args, **kwargs)

    def _format_usage(self, usage, actions, groups, prefix):
        return super(MyHelpFormatter, self)._format_usage(
            usage, actions, groups, prefix if prefix else "bla: ")

class MyArgumentParser(argparse.ArgumentParser):
    def __init__(self, *args, **kwargs):
        kwargs['formatter_class']=MyHelpFormatter
        super(MyArgumentParser, self).__init__(*args, **kwargs)


p = MyArgumentParser(description='Foo')
p.add_argument('foo', type=str)
print p.parse_args()

prints

python myargparse.py  --help
bla: myargparse.py [-h] foo

Foo

positional arguments:
  foo

optional arguments:
  -h, --help  show this help message and exit

_('usage: ') references gettext. In argparse.py, at the top, you have:

from gettext import gettext as _

You can muck around with gettext a bit.

Given a .po file:

msgid "usage: "
msgstr "foobar: "

You can convert it to a .mo file (for example here).

Afterwards (where ./foo/LC_MESSAGES/messages.mo is the result of compiling the .po):

~/Desktop> find . -name *mo
./foo/LC_MESSAGES/messages.mo
~/Desktop> cat myargparse2.py
import argparse
import gettext
gettext.bindtextdomain(gettext.textdomain(), '.')
p = argparse.ArgumentParser(description='Foo')
p.add_argument('foo', type=str)
print p.parse_args()
~/Desktop> LANGUAGE=foo python myargparse2.py
foobar: myargparse2.py [-h] foo
myargparse2.py: error: too few arguments

Use your desired languages instead of foo.

Vlad
  • 18,195
  • 4
  • 41
  • 71
  • 1
    Many thanks. I don't have any problem to mess with gettext, but the only solution I saw was a guy talking about "appending" the translation file to another one (I didn't understand much). If I can have the translation file inside my program directory, say "/home/me/project/translations" it is not a problem, but if I have to modify an existing Python's .mo file then I don't want to do it. Maybe you can put some light on it. I guess `argparse` has a `domain` or something like that where it looks for its translations – JorgeeFG Jan 05 '16 at 16:10
  • 1
    http://stackoverflow.com/questions/28730641/how-to-localize-pythons-argparse-module-without-patching-it – JorgeeFG Jan 05 '16 at 16:16
  • I added a proof of concept for adding a simple `.mo` file. I've never touched `gettext` before, so not sure if it's the right approach, but it seems to work. – Vlad Jan 05 '16 at 16:31
  • Hey I tested your approach and it works. gettext recommends using the Class API, so I tried, but can't get it to work. Do you have a clue? http://stackoverflow.com/questions/35347168/python-3-gettext-not-working-for-argparse – JorgeeFG Feb 11 '16 at 18:34
1

Based on Vlad's answer, I made it shorter:

class CustomHelpFormatter(argparse.HelpFormatter):
    def __init__(self, *args, **kwargs):
        super(CustomHelpFormatter, self).__init__(*args, **kwargs)

    def _format_usage(self, usage, actions, groups, prefix):
        return super(CustomHelpFormatter, self)._format_usage(
            usage, actions, groups, prefix if prefix else "Uso: ")


if __name__ == "__main__":

    parser = argparse.ArgumentParser(prog="jcheq.py",
                                     usage="%(prog)s [opciones] [paths...]\nThe paths are optional; if not given . is "
                                           "used.",
                                     add_help=False,
                                     formatter_class=CustomHelpFormatter)
JorgeeFG
  • 5,651
  • 12
  • 59
  • 92