Home

Awesome

Pomo

Pomo is a powerful implementation of gettext/dpgettext for Javascript that can be run both in the browser and Node as-is. It both reads PO files into memory and utilizes them for internationalization purposes.

Pomo reads PO files, eventually also MO files, and can load them from AJAX, special <link> tags and literal strings as explained below.

Pomo provides a simplistic interface to work with complex scenarios, being able to handle * term contexts (some terms in a given context might very well not mean the same thing in a different context) * term plurals * multiline msgid and msgstr definitions (except for plurals).

For more information, check the release notes

Usage example

//Browser example. Server would have it the same, just after calling Pomo = require('./pomo.js')
window.onload = function() {
    /*
    Set a default domain for the Pomo.getText calls. If omitted,
    all calls to getText need to pass the domain set on Pomo.load,
    unless none was passed, in which case getText doesn't require a domain
  */
    Pomo.domain = 'translation_domain';

    //return a plain string instead of a translation object
    Pomo.returnStrings = true;

    //Return unescaped strings ready for insertion instead of the original literal escaped string
    Pomo.unescapeStrings = true;

    //Let's load from a literal
    Pomo.load('\
        #: /path/to/file.php:110 \
        msgctxt "some context" \
        msgid "String to translate, with %s markers" \
        msgstr "Cadena a traducir, con marcadores de %s" \
    ', //the literal PO contents
    {
        format: 'po', // the file format, can potentially be 'po' or 'mo'
        mode: 'literal', // wether the passed resource is a 'literal', a 'link' or a 'remote' file
        translation_domain: 'translation_domain' //Loaded resources will be put under this domain if set.
    });

    var p = document.createElement('p');
    p.appendChild(
    document.createTextNode(
    Pomo.getText("String to translate, with %s markers", {
        variables: ["tipo printf"], //only needed if you pass markers
        context: 'optional context',
        /* if there is a context, a search is made
                             for the translation mapping to it               */
        domain: 'translation_domain'
        /* Only mandatory if there's an actual domain in use
                                and no default one was set via Pomo.domain */
    })));
    document.documentElement.appendChild(p);

    //now let's load from any amounts of <link type="text/x-gettext-translation"/> you might have on the page
    var lnk_deferred = Pomo.load(null, {
        format: 'po',
        mode: 'link', //the new mode, tells Pomo to find a <link id="%LINK_ELEMENT_NAME%" and fetch it
        translation_domain: 'entirely_different_translation_domain' //this one we'll put in another translation_domain
    });
        
    /*
    Pomo.load now returns a Deferred object, which can execute the
    passed function upon parsing all the remote data. The passed function will have this = the Pomo instance
  */
    lnk_deferred.ready(function() {
        var p = document.createElement('p');
        p.appendChild(
        document.createTextNode(
        this.getText("String to translate, with %s markers", {
            variables: ["printf-ish"],
            context: 'optional context',
            domain: 'entirely_different_translation_domain'
        })));

        document.documentElement.appendChild(p);
    });

    /*
    And now another translation_domain from a straight AJAX call
  */
    var ajax_deferred = Pomo.load('/ajax/valid/url', {
        format: 'po',
        mode: 'ajax',
        translation_domain: 'a_third_translation_domain'
    });

    /*
    The deferred object works exactly the same way, only this time we're making use of the last loaded domain.
  */
    ajax_deferred.ready(function() {
        var p = document.createElement('p');
        p.appendChild(
        document.createTextNode(
        this.getText("String to translate, with %s markers", {
            variables: ["printf-ish"],
            context: 'optional context',
            domain: 'a_third_translation_domain'
        })));

        document.documentElement.appendChild(p);
    });
};

A pretty thing to do is aliasing Pomo.getText(); to __(), like this:.

var __ = (function(){
  var _ = !!window.Pomo? window.Pomo : (!!window.__Pomo? window.__Pomo: false); //is Pomo there? get it
  var gettext_wrap = function(word, options){return _.getText(word, options)};  // aliases getText
  gettext_wrap = !!_? gettext_wrap: false; //if Pomo can be found, alias it
  if(!gettext_wrap){
    throw new "Pomo can't be found";
  }

  return gettext_wrap;
})();

Non-evident note: Pomo by default provides a kind of object that can be used as a string, but can be coerced into returning strings by setting Pomo.returnStrings = true