Question

The argparse module "automatically generates help and usage messages". I can give Non-English names to the arguments and provide Non-English help texts; but the help output then becomes a mixture of at least two languages, because terms like usage, positional arguments, optional arguments and show this help message and exit are automatically generated in English.

How can I replace this English output with translations?

Preferably, I would like to provide the translations within the script, so that the script generates the same output wherever it is started.

Edit: Based on the answer by Jon-Eric, here an example with his solution:

import gettext

def Übersetzung(Text):
    Text = Text.replace("usage", "Verwendung")
    Text = Text.replace("show this help message and exit",
                        "zeige diese Hilfe an und tue nichts weiteres")
    Text = Text.replace("error:", "Fehler:")
    Text = Text.replace("the following arguments are required:",
                        "Die folgenden Argumente müssen angegeben werden:")
    return Text
gettext.gettext = Übersetzung

import argparse

Parser = argparse.ArgumentParser()
Parser.add_argument("Eingabe")
Argumente = Parser.parse_args()

print(Argumente.Eingabe)

saved as Beispiel.py gives with python3 Beispiel.py -h the following help output:

Verwendung: Beispiel.py [-h] Eingabe

positional arguments:
  Eingabe

optional arguments:
  -h, --help  zeige diese Hilfe an und tue nichts weiteres
Was it helpful?

Solution 2

One way, from this post by Peter Otten:

I don't know much about gettext, but the following suggests that most strings in argparse are properly wrapped:

$ cat localize_argparse.py

import gettext

def my_gettext(s):
    return s.upper()
gettext.gettext = my_gettext

import argparse

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-V", action="version")
    args = parser.parse_args()

$ python localize_argparse.py -h USAGE: localize_argparse.py [-h] [-V]

OPTIONAL ARGUMENTS:   -h, --help  SHOW THIS HELP MESSAGE AND EXIT   -V
show program's version number and exit

The workaround for the "-V" option would be to add the help message explicitly

parser.add_argument("-V", ..., help=_("show..."))

You still have to provide all translations yourself.

OTHER TIPS

argparse uses the gettext API inspired by GNU gettext. You can use this API to integrate your translation of argparse in a relatively clean manner.

To do so, call the following code before argparse outputs any text (but possibly after import argparse):

import gettext

# Use values that suit your project instead of 'argparse' and 'path/to/locale'
gettext.bindtextdomain('argparse', 'path/to/locale')
gettext.textdomain('argparse')

In order for this solution to work, your translation of argparse must be located at path/to/locale/ll/LC_MESSAGES/argparse.mo where ll is the code of the current language (for example de; can be configured for example by setting the environment variable LANGUAGE).

How do you generate the .mo file?

  1. pygettext --default-domain=argparse /usr/local/lib/python3.5/argparse.py
    • Use the actual location of argparse.py
    • Creates the file argparse.pot
  2. cp argparse.pot argparse-ll.po
    • Use an actual language code instead of ll
  3. Fill in the missing translation strings in argparse-ll.po
  4. msgfmt argparse-ll.po -o locale/ll/LC_MESSAGES/argparse.mo

See gettext documentation for details about creating .mo file.

I have published these instructions in more detail in README.md of my Czech translation of argparse.

Here is a solution with French translation, where one creates a conversion dict that holds the translation for the encountered English keywords

def convertArgparseMessages(s):
    subDict = \
    {'positional arguments':'Arguments positionnels',
    'optional arguments':'Arguments optionnels',
    'show this help message and exit':'Affiche ce message et quitte'}
    if s in subDict:
        s = subDict[s]
    return s
gettext.gettext = convertArgparseMessages
import argparse

Here is a Python module to translate all messages emitted by argparse. It is intended for a quick and dirty translation to only one other language (French in my case, but feel free to adjust that for your own language). For a more industrial multilingual approach, look at the excellent Filip Bartek solution.

"""
This module is like argparse but in french. 
Import it and use it like you would use argparse.

DIRECTIVES:
First copy-paste this code in a separate new file named french_argparse.py
Put this new file beside your main.py file in the same top project folder.
Then in the main.py file, import it like this:

>>> import french_argparse as argparse
"""

import gettext

#################################################################################################################
# The following translations are in French, but feel free to replace them with your own
# Many messages are even not translated, because they seems to be more intended for the programmer than the user.
# Phrases were extracted from the code at (https://github.com/python/cpython/blob/master/Lib/argparse.py)
# On October 2019
#################################################################################################################

__TRANSLATIONS = {
    'ambiguous option: %(option)s could match %(matches)s': 'option ambiguë: %(option)s parmi %(matches)s',
    'argument "-" with mode %r': 'argument "-" en mode %r',
    'cannot merge actions - two groups are named %r': 'cannot merge actions - two groups are named %r',
    "can't open '%(filename)s': %(error)s": "can't open '%(filename)s': %(error)s",
    'dest= is required for options like %r': 'dest= is required for options like %r',
    'expected at least one argument': 'au moins un argument est attendu',
    'expected at most one argument': 'au plus un argument est attendu',
    'expected one argument': 'un argument est nécessaire',
    'ignored explicit argument %r': 'ignored explicit argument %r',
    'invalid choice: %(value)r (choose from %(choices)s)': 'choix invalide: %(value)r (parmi %(choices)s)',
    'invalid conflict_resolution value: %r': 'invalid conflict_resolution value: %r',
    'invalid option string %(option)r: must start with a character %(prefix_chars)r':
        'invalid option string %(option)r: must start with a character %(prefix_chars)r',
    'invalid %(type)s value: %(value)r': 'valeur invalide de type %(type)s: %(value)r',
    'mutually exclusive arguments must be optional': 'mutually exclusive arguments must be optional',
    'not allowed with argument %s': "pas permis avec l'argument %s",
    'one of the arguments %s is required': 'au moins un argument requis parmi %s',
    'optional arguments': 'arguments optionnels',
    'positional arguments': 'arguments positionnels',
    "'required' is an invalid argument for positionals": "'required' is an invalid argument for positionals",
    'show this help message and exit': 'afficher ce message et quitter',
    'unrecognized arguments: %s': 'argument non reconnu: %s',
    'unknown parser %(parser_name)r (choices: %(choices)s)': 'unknown parser %(parser_name)r (choices: %(choices)s)',
    'usage: ': 'usage: ',
    '%(prog)s: error: %(message)s\n': '%(prog)s: erreur: %(message)s\n',
    '%r is not callable': '%r is not callable',
}


gettext.gettext = lambda text: __TRANSLATIONS[text] or text

##############################################################################
# Now import all argparse functionalities inside this module.
#
#   NB Many linters don't like the following line of code so we have disabled
#   warnings for pylint, flake8 and PyCharm
##############################################################################

# pylint: disable=all
# noinspection PyUnresolvedReferences
from argparse import *                  # noqa

I was faced with a similar problem. Almost all messages will translated properly doing as described in post 5, but not the help messages added with parser.add_argument(). You can solve the problem by using non-class-based gettext for argparse and class-based gettext for the app. Have a look at app3.py in https://github.com/jmo3300/py01_i18n_01

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top