Grunt xgettext plugin for JavaScript and Handlebars
JavaScript HTML
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


Grunt xgettext plugin for JavaScript, HTML and Handlebars


Gettext is the name of a set of utilities developed by GNU to add multi-language support to applications.

The first step of the translation process is to extract translatable messages from your sources. To do so, you should mark all strings which you want to translate by wrapping them in a translator function (often called tr(), _() or i18n()). The xgettext task provided by this plugin then scans all your source files and generates a POT file containing all the translatable strings. In addition to scanning plain JavaScript files, this plugin also supports scanning HTML and Handlebars templates.

The second step is converting the POT file into a PO file which is the file that will be actually translated by translators. During this step you can merge the POT file with a previously translated PO file resulting in a new PO file that has all known translations already filled in. This step can be performed using the msgmerge command-line utility. It is not provided by this plugin, but an example of calling the utility through the Grunt Shell plugin is given below as part of the real-world example.

The third step is taking the translated PO files and getting the translations to show up in your project. In order to facilitate this, use the po2json from the grunt-po2json plugin which converts the translations to a JSON map, optionally wrapped in a Require.js definition. To finish this step, you will have to make sure the JSON translations are loaded into your application and actually used by the tr(), _() or i18n() function you use.

Happy translating!

To find more information about the original gettext utilities, visit the GNU project:

GNU also maintains a list of additional tools to work with PO files, including translation programs useful for translators:

Getting Started

This plugin requires Grunt ~0.4.5

If you haven't used Grunt before, be sure to check out the Getting Started guide, as it explains how to create a Gruntfile as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:

npm install grunt-xgettext --save-dev

Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:


The "xgettext" task


In your project's Gruntfile, add a section named xgettext to the data object passed into grunt.initConfig().

  xgettext: {
    options: {
      functionName: "tr",
      potFile: "messages.pot",
      //processMessage: function(message) { ... }
    target: {
      files: {
        handlebars: [],
        javascript: []



Type: String Default value: "tr"

The function name that marks translatable messages.


Type: String Default value: "messages.pot"

The .pot file that is generated by this task (the output file). It will contain all extracted messages, regardless of the source in which they were found (be it Handlebars or JavaScript files).

Warning: This file is overwritten every time you run this task.


Type: Function Default value: _.identity

Custom function that will process every extracted message before it's included in the POT file. This may come in handy, for example, if you want to simplify whitespace.

The function takes the message string as its sole argument and should return the processed message.


Type: Array Default value: undefined

An array in which you may define any headers you want to appear in the .pot file, such as project id, creation and revision dates, content type, encodings, etc.

The array elements should be strings, ending with escaped '\n':

header: [
    '"Project-Id-Version: KypyMypy\\n"',
    '"POT-Creation-Date: ' + (new Date()).toString() + '\\n"',
    '"PO-Revision-Date: ' + (new Date()).toString() + '\\n"',
    '"Content-Type: text/plain; charset=UTF-8\\n"',
    '"Content-Transfer-Encoding: 8bit\\n"'



Handlebars files to scan for translatable messages.

Assuming the default functionName is used, translatable messages look like this:

{{tr "Some translatable message"}}

{{tr "You have %1 follower" "You have %1 followers" numFollowers}}

In both cases, all string arguments inside the {{tr ...}} invocation are extracted as translatable messages.


HTML files to scan for translatable messages.

Assuming the default functionName is used, translatable messages look like this:

tr("Some translatable message")

tr("You have %1 follower" "You have %1 followers" numFollowers)

In both cases, all string arguments inside the tr() invocation are extracted as translatable messages.


JavaScript files to scan for translatable texts.

Assuming the default functionName is used, translatable messages look like this:

tr("Some translatable messages")

tr("You have %1 follower", "You have %1 followers").arg(numFollowers)

In both cases, all string arguments inside the tr() function call are extracted as translatable messages.

Be aware that concatenating translatable strings with variables is inherently not possible. For example, this will NOT work:

tr("Some value: " + value)

The reason this fails is because the input to the tr() function will be different every time it is called, and therefore does not have a stable key for looking up the proper translation.

Note that concatenating multiple strings to create a single (multi-line) translatable string does work with JavaScript files. Example:

tr("This is the first line " +
   "of a multiline translatable message")

Context and Comments

Finally, you can pass context and comments for your messages by using an options object. Examples:

tr("September", { comment: "Translators: use all lower-case if months are not " +
                           "capitalized in your language" })

tr("May", { context: "Abbreviation", comment: "Abbreviation of May" })
tr("Sept.", { context: "Abbreviation", comment: "Abbreviation of September" })

For Handlebars templates, you can achieve the same effect through named arguments:

{{tr "May" context="Abbreviation" comment="Abbreviation of May"}}

For JavaScript, you can also use triple-slash comments to provide translator comment:

/// Translators: use all lower-case if months are not capitalized in your language

Usage Examples

Real-world example

var _ = grunt.util._;

var locales = ["de-DE", "en-GB", "en-US", "fr-FR", "it-IT", "ja-JP", "nl-NL"];

  xgettext: {
    target: {
      files: {
        handlebars: ["tmpl/**.handlebars"],
        javascript: ["js/**.js"]
      options: {
        functionName: "i18n",
        potFile: "translations/messages.pot",
        processMessage: function(message) {
          return message.replace(/\s+/g, " "); // simplify whitespace

  po2json: {
    target: {
      src: ["translations/*.po"],
      dest: ["translations/"],
      options: {
        requireJs: true

  shell: {
    options: {
      failOnError: true
    msgmerge: {
      command:, function(locale) {
        var po = "translations/" + locale + ".po";
        return "if [ -f \"" + po + "\" ]; then\n" +
               "    echo \"Updating " + po + "\"\n" +
               "    msgmerge " + po + " translations/messages.pot > .new.po.tmp\n" +
               "    exitCode=$?\n" +
               "    if [ $exitCode -ne 0 ]; then\n" +
               "        echo \"Msgmerge failed with exit code $?\"\n" +
               "        exit $exitCode\n" +
               "    fi\n" +
               "    mv .new.po.tmp " + po + "\n" +


In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using Grunt.

Release History


  • Added Underscore templates extractor.


  • Bugfixes for multi-line translator comments.


  • Introduced support for triple-slash translator comments in JavaScript extractor.


  • Introduced new Handlebars extractor, with support for context and comment options.
  • Bugfixes for JavaScript extractor.


  • Bugfixes for JavaScript extractor.


  • Introduced new JavaScript extractor, with support for context and comment options.