========
Linting!
========

Help
====

::

    $ dennis-cmd lint --help

This will list the available lint rules and codes, the variable
formats and any additional options available.


Summary
=======

Dennis can lint your translated PO files for Python formatting
token issues::

    $ dennis-cmd lint messages.po


This runs multiple lint rules on all the strings in the PO file
generating a list of errors and a list of warnings.

Dennis can also lint your POT files and point out issues that can
result in poor translations. You can lint POT files like this::

    $ dennis-cmd lint messages.pot


Skipping rules string-by-string
===============================

In the extracted comment, you can tell Dennis to ignore lint rules (or
all lint rules).

Ignore everything::

    #. dennis-ignore: *
    msgid "German makes up 10% of our visitor base"
    msgstr "A német a látogatóbázisunk 10%-át teszi ki"

Ignore specific rules (comma-separated)::

    #. dennis-ignore: E101,E102,E103
    msgid "German makes up 10% of our visitor base"
    msgstr "A német a látogatóbázisunk 10%-át teszi ki"

Ignore everything, but note the beginning of the line is ignored by
Dennis so you can tell localizers to ignore the ignore thing::

    #. localizers--ignore this comment. dennis-ignore: *
    msgid "German makes up 10% of our visitor base"
    msgstr "A német a látogatóbázisunk 10%-át teszi ki"


Warnings and Errors
===================

What's a warning?
-----------------

Warnings indicate the translated string is either outdated or a poor
translation, but the string is fine in the sense that it won't kick
up an error in production.

For example, say the original string has a variable, but the
translated string doesn't use that variable.

That's not great and probably means the translated string needs to be
updated, but it won't throw an error in production.


What's an error?
----------------

Errors indicate problems with the translated string that will cause
an error to be thrown. These should get fixed pronto.

For example, when the translated string has a Python variable that's
not in the original string. When this string is interpolated, it will
kick up a Python error. That causes the software to die, users to be
unhappy, tires to go flat, people to work on weekends, mass hysteria,
etc. No one likes that. I don't like that. You probably don't like
that, either.


Table of Warnings and errors
============================

PO files
--------

+------+-----------------------------------------------------------------------+
| Code | Description                                                           |
+======+=======================================================================+
| E101 | Malformed variable missing type                                       |
|      |                                                                       |
|      | Only checks python-format variables.                                  |
|      |                                                                       |
|      | Example (Python)::                                                    |
|      |                                                                       |
|      |     Error: malformed variables: %(count)                              |
|      |     msgid: "%(count)s view"                                           |
|      |     msgstr: "%(count) view"                                           |
|      |                                                                       |
|      | >>> "%(count) view" % {"count": 5}                                    |
|      | Traceback (most recent call last):                                    |
|      |   File "<stdin>", line 1, in <module>                                 |
|      | ValueError: unsupported format character 'v' (0x76) at index 9        |
|      | >>>                                                                   |
|      |                                                                       |
+------+-----------------------------------------------------------------------+
| E102 | Malformed variable missing right curly-brace                          |
|      |                                                                       |
|      | For example ``{foo`` with missing ``}``.                              |
|      |                                                                       |
|      | Only checks python-brace-format variables.                            |
|      |                                                                       |
|      | Example (Python)::                                                    |
|      |                                                                       |
|      |     Error: malformed variables: {foo bar baz                          |
|      |     msgid: "{foo} bar baz"                                            |
|      |     msgstr: "{foo bar baz"                                            |
|      |                                                                       |
|      | >>> "{foo bar baz".format(foo="some thing")                           |
|      | Traceback (most recent call last):                                    |
|      |   File "<stdin>", line 1, in <module>                                 |
|      | ValueError: unmatched '{' in format                                   |
|      | >>>                                                                   |
|      |                                                                       |
+------+-----------------------------------------------------------------------+
| E103 | Malformed variable missing left curly-brace                           |
|      |                                                                       |
|      | For example ``foo}`` with missing ``{``.                              |
|      |                                                                       |
|      | Only checks python-brace-format variables.                            |
|      |                                                                       |
|      | Example (Python)::                                                    |
|      |                                                                       |
|      |     Error: malformed variables: foo}                                  |
|      |     msgid: "{foo} bar baz"                                            |
|      |     msgstr: "foo} bar baz"                                            |
|      |                                                                       |
|      | >>> "foo}".format(foo="some thing")                                   |
|      | Traceback (most recent call last):                                    |
|      |   File "<stdin>", line 1, in <module>                                 |
|      | ValueError: Single '}' encountered in format string                   |
|      | >>>                                                                   |
|      |                                                                       |
+------+-----------------------------------------------------------------------+
| E104 | Bad format character                                                  |
|      |                                                                       |
|      | For example ``%a``.                                                   |
|      |                                                                       |
|      | Only checks python-format variables.                                  |
|      |                                                                       |
|      | Example (Python)::                                                    |
|      |                                                                       |
|      |     Error: bad format character: %a                                   |
|      |     msgid: "%s foo"                                                   |
|      |     msgstr: "%a FOO"                                                  |
|      |                                                                       |
|      | >>> "%a" % (1, 2, 3)                                                  |
|      | Traceback (most recent call last):                                    |
|      |   File "<stdin>", line 1, in <module>                                 |
|      | ValueError: unsupported format character 'a' (0x61) at index 1        |
|      | >>>                                                                   |
|      |                                                                       |
+------+-----------------------------------------------------------------------+
| E201 | Invalid variables in translated string                                |
|      |                                                                       |
|      | There are formatting variable tokens in the *translated* string       |
|      | that aren't in the original string.                                   |
|      |                                                                       |
|      | Example::                                                             |
|      |                                                                       |
|      |     Error: mismatched: invalid variables: {helpurl}                   |
|      |     msgid: "You can find help at {url}"                               |
|      |     msgstr: "You can find help at {helpurl}"                          |
|      |                                                                       |
|      | In this example, "helpurl" won't be in the list of variables to       |
|      | interpolate and this will throw a KeyError. That's equivalent         |
|      | to this:                                                              |
|      |                                                                       |
|      | >>> "You can find help at {helpurl}".format(url="http://example.com") |
|      | Traceback (most recent call last):                                    |
|      |   File "<stdin>", line 1, in <module>                                 |
|      | KeyError: 'helpurl'                                                   |
|      | >>>                                                                   |
|      |                                                                       |
+------+-----------------------------------------------------------------------+
| W202 | Missing variables in translated string                                |
|      |                                                                       |
|      | There are formatting variable tokens in the *original* string         |
|      | that aren't in the *translated* string.                               |
|      |                                                                       |
|      | Example::                                                             |
|      |                                                                       |
|      |     Warning: missingvars: missing variables: {url}                    |
|      |     msgid: "You can find help at {url}"                               |
|      |     msgstr: "Get help!"                                               |
|      |                                                                       |
+------+-----------------------------------------------------------------------+
| E202 | Missing variables in translated string                                |
|      |                                                                       |
|      | For python-format positional variables (e.g. ``%s``), it's an         |
|      | error when the variable is missing from the translated string.        |
|      |                                                                       |
|      | Example::                                                             |
|      |                                                                       |
|      |     Error: missingvars: missing variables: %s                         |
|      |     msgid: "foo %s"                                                   |
|      |     msgstr: "FOO"                                                     |
|      |                                                                       |
+------+-----------------------------------------------------------------------+
| W301 | String is all whitespace                                              |
|      |                                                                       |
|      | The translated string is all whitespace.                              |
|      |                                                                       |
|      | Example::                                                             |
|      |                                                                       |
|      |    Error: blank: translated string is solely whitespace               |
|      |    msgid: "Foo"                                                       |
|      |    msgstr: "  "                                                       |
|      |                                                                       |
+------+-----------------------------------------------------------------------+
| W302 | Translated string is identical to source string                       |
|      |                                                                       |
|      | Example::                                                             |
|      |                                                                       |
|      |    Error: unchanged: translated string is same as source string       |
|      |    msgid: "Foo"                                                       |
|      |    msgstr: "Foo"                                                      |
|      |                                                                       |
+------+-----------------------------------------------------------------------+
| W303 | HTML is mismatched between source and translated strings              |
|      |                                                                       |
|      | Example::                                                             |
|      |                                                                       |
|      |    Error: html: different html: "<b>" vs. "<i>"                       |
|      |    msgid: "<b>Foo</b>"                                                |
|      |    msgstr: "<i>Feh</i>"                                               |
|      |                                                                       |
+------+-----------------------------------------------------------------------+
| W304 | HTML is invalid and can't be parsed                                   |
+------+-----------------------------------------------------------------------+


POT files
---------

+------+-----------------------------------------------------------------------+
| Code | Description                                                           |
+======+=======================================================================+
| W500 | Hard to read variable name                                            |
|      |                                                                       |
|      | There are a series of letters and numbers which are hard to           |
|      | distinguish from one another: o, O, 0, l, 1. It's not uncommon        |
|      | for a hard-working translator to misread and use the wrong character. |
|      |                                                                       |
|      | Example::                                                             |
|      |                                                                       |
|      |     Warning: hardtoread: hard to read variable name "l"               |
|      |     msgid: "Title: {l}"d help at {url}"                               |
|      |     msgstr: ""                                                        |
|      |                                                                       |
+------+-----------------------------------------------------------------------+
| W501 | One character variable name                                           |
|      |                                                                       |
|      | Using a one character variable name doesn't give enough context to    |
|      | the translator about what's being put in that variable.               |
|      |                                                                       |
|      | Example::                                                             |
|      |                                                                       |
|      |     Warning: onechar: one character variable name: "{t}"              |
|      |     msgid: "{t} | {c}"                                                |
|      |     msgstr: ""                                                        |
|      |                                                                       |
+------+-----------------------------------------------------------------------+
| W502 | Multiple unnamed variables                                            |
|      |                                                                       |
|      | Having one unnamed variable is ok since it's not order-dependent.     |
|      | However, having more than one unnamed variable means those variabes   |
|      | must occur in an order specified outside of the string. This creates  |
|      | problems with RTL languages and any other language that might need to |
|      | change the order of the variables to create a translation that makes  |
|      | sense.                                                                |
|      |                                                                       |
|      | Example::                                                             |
|      |                                                                       |
|      |    Warning: multiple variables with no name                           |
|      |    msgid: "%s replies to %s"                                          |
|      |    msgstr: ""                                                         |
|      |                                                                       |
+------+-----------------------------------------------------------------------+
