I am trying to i18n/internationalize an existing python django project. That means adding lots of _ to strings in my python code. There are a lot of strings to go through, and it's very likely that I could miss some.
Pylint to the rescue
pylint is a great tool to analyze your python code to find errors. You can also write custom pylint checkers/plugins/modules to check for specific things.
I wrote a pylint plugin to check for all strings that look like they should be translated/i18n'ed, and raise a warning message if they are not.
pylint checker for missing gettext
The package is in PyPI, get it with pip install pylint-i18n
.
The code for pylint-i18n is on github. Download missing_gettext.py directly.
To use it, make sure that python module is in your PYTHONPATH (if you used pip, this is all done for you already), and then call pylint link this: pylint --load-plugins=missing_gettext /path/to/python/file.py
How does it work
Pylint walks through the parse tree of your python programme. Everytime it sees a constant, it calls this module. If the constant is a string, and the value has not been whitelisted, then this module walks up the parse tree from this string. At each point it checks if the current node in the tree is a call to _
, ugettext
or ugettext_lazy
. If so, then this string has been translated, and is OK. It also checks if the current position is one of the whitelisted structures (e.g. is it a call to the django logging method), if so, it ignores this string.
If none of these checks pass, then the string is assumed to be bad, and pylint attaches a warning message to it
Examples
Input
print "Hello"
Output
test.py:1: [W] non-gettext-ed string 'Hello'
Input
def something(arg):
"""This is a function"""
return arg['some']
Output
(No output because nothing needs translating)
Input
def something(arg):
"""This is a function"""
return "Somestring %d" % arg['some']
Output
test.py:3: [W, something] non-gettext-ed string 'Somestring %d'
Input
def something(arg):
"""This is a function"""
return "Somestring %d" % arg['some']
def another():
print "Hello again"
Output
test.py:3: [W, something] non-gettext-ed string 'Somestring %d'
test.py:6: [W, another] non-gettext-ed string 'Hello again'
Whitelisted text
The first time I ran this is caught loads of text that wasn't passed through gettext, such as dictionary['key']
access. The current code has several checks, based on the value of the string, or the location of the string in the source code, that can make a potentially untranslated string be ignored. e.g. if the string is empty, the string is the key in a dictionay, etc., then ignore it.
These ignore-rules are tailored to my django project, you may want to change them to suit your django project, or if you are not using it for a django project, you should disable them.
Todo
- Make a proper python package and upload to PyPI.
- Add options to disable the django-specific checks so it can work well on non-django projects.
- It's currently using warning message id
W9903
, since that one is free, I'm not sure this is the best way.
Download
The code for pylint-i18n is on github. Download missing_gettext.py directly.