A TEXT POST

Dealing with translations in nodejs

Dealing with translations is always a difficult task.

Since gettext was not a option for my needs, I developed a nodejs alternative following this philosophy:

  • Scalable: The translations should be available to any number of machines.

  • Fast: Getting translations from memory.

  • Reliable: Translations should be always available on a central repository/database.

  • Flexible: You should be able to use your favorite storage solution.

dialect http://github.com/masylum/dialect

dialect-http http://github.com/masylum/dialect-http

connect-i18n http://github.com/masylum/connect-i18n

To see how these modules work I recorded a screencast tutorial.

Watch screencast

This is my first screencast, so please, be kind.

Code

app.js

require('colors');

var SERVER = {},
    Server = require('mongodb/connection').Server,
    Db = require('mongodb/db').Db,
    db = new Db('example', new Server('localhost', 27017, {auto_reconnect: true, native_parser: true})),
    express = require('express'),
    port = 3000,
    app = express.createServer(),
    dialect = require('dialect').dialect({locales: ['es', 'en'], store: {mongodb: {}}}),
    funk = require('funk')();

SERVER.app = app;
SERVER.db = db;
SERVER.dialect = dialect;

SERVER.model = function (mod) {
  return require('./models/' + mod)(SERVER);
};

// Configuration
app.configure(function () {
  app.use(express.favicon());
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express['static'](__dirname + '/public'));
  app.use(express.bodyParser());

  app.use(express.cookieParser());
  app.use(express.session({secret: 'whatever'}));

  app.use(require('connect-i18n')());
  app.use(require('./middlewares/locales')(SERVER, {}));

  app.use(app.router);

});

// Helpers
app.helpers(require('./helpers/static')(SERVER, {}));
app.dynamicHelpers(require('./helpers/dynamic')(SERVER, {}));

// Controllers
require('./controllers/public')(SERVER, {});

// Open databases and listen
console.log('Opening the database ...'.grey);

dialect.connect(funk.add(function () {
  console.log('+ dialect ready'.blue);
}));

db.open(funk.add(function () {
  console.log('+ mongo ready'.blue);
}));

// when mongo and dialect are ready...
funk.parallel(function () {
  // sync store and memory cache every 5 secs
  dialect.sync({interval: 5 * 1000}, function () {
    app.listen(port);
    console.log('Listening port '.green + port.toString().yellow);
  });
});

helpers/static.js

module.exports = function (SERVER, options) {
  return {
    truncate: function (str, num) {
      var limit = num || 20;

      if (str && str.length > limit) {
        return str.slice(0, limit) + '...';
      } else {
        return str;
      }
    },

    dateFormat: require('dateformat'),

    '_': SERVER.dialect.get,

    dialect: SERVER.dialect
  };
};

views/layout.jade

!!!
html
  head
    title= title || ''
    link(rel: 'stylesheet', href: '/css/reset.css' )
    link(rel: 'stylesheet', href: '/css/global.css' )

    -var css
    -if(css)
      -each file in css
        link(rel: 'stylesheet', href: '/css/' + file + '.css' )
  body
    nav#header
      .wrapper
        a#logo(href: '/')= _('Products')

    .clearer

    .wrapper
      #content!= body

      ul#locales
        -each locale in dialect.config('locales')
          li
            a(href: '?locale=' + locale)= locale

  -var js
  -if(js)
    script(src: 'http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js')
    script(src: '/javascripts/global.js' )

    -each file in js
      script(src: '/javascripts/' + file + '.js' )

middlewares/locales.js

module.exports = function (SERVER, options) {
  return function (req, res, next) {
    var url = require('url').parse(req.url, true),
        setLocale = function (locale) {
          var has_locale = SERVER.dialect.config('locales').indexOf(locale) !== -1;
          if (has_locale) {
            SERVER.dialect.config('current_locale', locale);
            req.session.current_locale = locale;
          }
          return has_locale;
        };

    // url
    if (url.query && url.query.locale) {
      setLocale(url.query.locale);
    // session
    } else if (req.session.current_locale) {
      setLocale(req.session.current_locale);
    // browser
    } else {
      req.locales.some(setLocale);
    }
    next();
  };
};
A TEXT POST

Welcome

Hey!

Pau Ramon its here, posting some development thoughts and other nerdities.