Lint HTML and template source files for hardcoded strings



Installing i18n-lint globally via npm gives you the i18n-lint binary.

        $ npm install -g jwarby/i18n-lint
        $ i18n-lint --help

Usage: i18n-lint [OPTIONS] <file ...>


    -h, --help                              output usage information
    -V, --version                           output the version number
    -a, --attributes <attributes>           Comma-separated list of HTML attributes to lint (default: 'alt,title')
    -i, --ignore-tags <tags>                Comma-separated list of names of tags to ignore whilst linting (default: 'script,style')
    -t, --template-delimiters <delimiters>  Template delimiters used in source files.  For example, Mustache-like templating languages should use ''
    -r, --reporter <reporter>               Specify which reporter to output results with
    --exclude <exclusion patterns>          Comma-separated list of glob patterns to ignore,  e.g. "/test_subdir/,ignored.html"
    --color                                 Force colored output
    --no-color                              Disable colored output

  Use `man i18n-lint` for more information


i18n-lint can be used in other projects as a library. After installing, simply require the module.

        $ npm install --save jwarby/i18n-lint
        var i18nlint = require('i18n-lint');

// Lint a file
var errors = i18nlint('myfile.html', {
  // ... options ...

// Lint a string
var errors = i18nlint.scan('<div>Untranslated String!</div>', {
  // ...options...

Grunt Plugin

i18n-lint is also available as a grunt plugin: grunt-i18nlint.

        $ npm install --save-dev jwarby/grunt-i18nlint
        // Gruntfile.js

  // ... snip ...
  i18nlint: {
    // ... task config ...
  // ... snip ...
Back to top



After installing, you should be able to type i18n-lint into a terminal.
# Display version and exit
$ i18n-lint --version

# Lint myfile.html
$ i18n-lint myfile.html

# Lint all HTML files using a glob pattern
$ i18n-lint views/**/*.html

# Set options using --<option name> <optionValue>
$ i18n-lint --some-option "someValue" views/**/*.html


After installing, you can require the i18n-lint lint module in your code.
// Require the module
var i18nlint = require('i18n-lint');

// Lint myfile.html
var errors = i18nlint('myfile.html');

// Lint all HTML files using a glob pattern
var errors = i18nlint('views/**/*.html');

// Set options using an object as the second parameter
var errors = i18nlint('views/**/*.html', { /*some options*/ });
Back to top


i18n-lint uses JavaScript functions to handle the output/processing of the errors collected by i18n-lint.

For example, here's a basic reporter which reports a count of hardcoded strings for each file which contained them:

// ~/my_awesome_reporter.js
module.exports = function(errors) {
    var len = errors.length,

    if (len) {
      filename = errors[0].file;
      process.stdout.write(filename + '\n -- ' + len + ' hardcoded string(s)\n');
This would produce output similar to:
$ i18n-lint --reporter ~/my_awesome_reporter.js *.html
 -- 3 hardcoded string(s)
 -- 1 hardcoded string(s)
 -- 4 hardcoded string(s)

Built-in reporters

Name Sample Output
     2 |   <h1>Hardcoded h1</h1>
               ^ Hardcoded <h1> tag
     3 |   <a href="#" alt="hardcoded alt"><%= translation %></a>
                            ^ Hardcoded alt attribute
# file:line:column reason
test/fixtures/1.html:2:6 Hardcoded &lt;h1&gt; tag
test/fixtures/1.html:3:19 Hardcoded alt attribute
    "file": "test/fixtures/1.html",
    "error": {
      "id": "(error)",
      "code": "W001",
      "reason": "Hardcoded <h1> tag",
      "evidence": "/(Hardcoded h1)/",
      "line": 2,
      "character": 6,
      "scope": "  <h1>Hardcoded h1</h1>"
    "file": "test/fixtures/1.html",
    "error": {
      "id": "(error)",
      "code": "W002",
      "reason": "Hardcoded 'alt' attribute",
      "evidence": "/(hardcoded alt)/",
      "line": 3,
      "character": 19,
      "scope": "  <a href=\"#\" alt=\"hardcoded alt\"><%= translation %></a>"
Back to top



-h, --help

Display help text, then exit

-V, --version

Display version information, then exit

-a, --attributes <attributes>

Set which HTML attributes to check. Defaults to 'alt,title'

-i, --ignore-tags <tags>

Set which HTML elements should be ignored when searching for hardcoded strings. Defaults to 'style,script'

-t, --template-delimiters <delimiters>

Define the template delimiters that the input files use. For instance, templating languages with a Mustache-like syntax should set this value to '{{,}}'

-r, --reporter <reporter>

Choose which report to output the results with. Defaults to 'default'. JSHint reporters can also be used.



Set which HTML attributes to check. Defaults to ['alt', 'title']


Set which HTML elements should be ignored when searching for hardcoded strings. Defaults to ['style', 'script']


Define the template delimiters that the input files use. For instance, templating languages with a Mustache-like syntax should set this value to ['{{', '}}']

Returned Data

The i18nlint function returns an array containing objects which describe the error. Each object looks like this:
  file: String, // the file that was being linted when the error was found
  error: {
    id: String, // id of the error, ususally '(error)'
    code: String, // the error code, e.g. 'W001', 'W002', etc
    reason: String, // description of the problem
    evidence: RegExp, // a regular expression, where error-causing parts of the string are captured in match groups
    line: Number, // the line number of the error
    character: Number, // the column number of the error
    scope: String // where the error was found

Error Codes

Code Meaning
W001 Element's text node content is a hardcoded string
W002 Element's attribute value is a hardcoded string

Using Reporters

Reporters can still be used when using i18n-lint as a library. Built-in reporters are stored in i18nlint.reporters:

var i18nlint = require('i18n-lint');

// {
//   default: [Function]
// }
Back to top



Lint a single HTML file

      $ i18n-lint index.html

Lint a single EJS file

$ i18n-lint -t "<%,%>" index.ejs
$ i18n-lint --template-delimiters "<%,%>" index.ejs

Lint multiple files

$ i18n-lint *.html
$ i18n-lint somewhere/**/*.html

Check 'content', 'title' and 'alt' HTML attributes

$ i18n-lint -a "content,title,alt" *.html
$ i18n-lint --attributes "content,title,alt" *.html

Ignore all 'script', 'style' and 'meta' tags

$ i18n-lint -i "script,style,meta" *.html
$ i18n-lint --ignore-tags "script,style,meta" *.html


Lint a single HTML file

      var errors = i18nlint('myfile.html');

Lint a single EJS file

var errors = i18nlint('myfile.ejs', {
  templateDelimiters: ['<%', '%>']

Lint multiple files

      var errors = i18nlint('somewhere/**/*.html');

Check 'content', 'title' and 'alt' HTML attributes

var errors = i18nlint('myfile.ejs', {
  attributes: ['content', 'title', 'alt']

Ignore all 'script', 'style' and 'meta' tags

var errors = i18nlint('myfile.ejs', {
  ignoreTags: ['script', 'style', 'meta']
Back to top


i18n-lint by jwarby

License Information

Licensed under the MIT license.

Bugs, Support and Feature Requests

Please post a new issue on the project issue tracker.


To see all releases of the plugin, please visit the releases page on GitHub


GitHub version Build Status Dependency Status devDependency Status Code Climate Test Coverage Untranslated strings which affect i18n

Back to top