The argparse module \"automatically generates help and usage messages\". I can give Non-English names to the arguments and provide Non-English help texts; b
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
).
.mo
file?pygettext --default-domain=argparse /usr/local/lib/python3.5/argparse.py
argparse.py
argparse.pot
cp argparse.pot argparse-ll.po
ll
argparse-ll.po
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.
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
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.
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
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