Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polyglot.js integration #298

Closed
ghost opened this issue Feb 9, 2014 · 4 comments
Closed

Polyglot.js integration #298

ghost opened this issue Feb 9, 2014 · 4 comments
Labels

Comments

@ghost
Copy link

ghost commented Feb 9, 2014

I want to know if someone has already integrated Polyglot.js with Rendr.

For now, I integrated Polyglot like this:

app/app.js:

  var Polyglot = require('node-polyglot');
  ....
  postInitialize: function() {
    var polyglot = new Polyglot({ locale: 'fr' });
      polyglot.extend({
        'msg': 'my content'
    });
  }
  ...

handlebars_helpers.js:

module.exports = function(Handlebars) {
  return {
    t: function (key, params) {
      var app = isServer ? this._app : window.App;
      return app.polyglot.t(key, params.hash);
    }
  };
};

In fact, I want to know the best place to store my localized strings.

@zcei
Copy link

zcei commented Aug 19, 2014

I'm trying to do the same as you, as we also need rendr & polyglot.

Actually I didn't get your sample code to work in my case - isServer was not defined.
app.polyglot also isn't callable for me.

I wrote a middleware to set a Polyglot instance into the app.attributes, which works pretty fine, but only for the initial request.
This is due to the fact, that I set it via app.set(), which serializes the content to JSON and thus loosing all functions. See here

How did you manage to have it always available?

The way I store my files (may still be interesting to you?!):

var locales   = require('../../locales');
  ...
// Loads proper set of phrases, based on `language` attribute returned by the API
if (typeof locales[lang_code] !== 'undefined') {
  phrases = locales[lang_code];
} else {
  // default to 'en'
  phrases = locales.en;
}

// Adds phrases to polyglot and sets locale for proper pluralization
polyglot.extend(phrases);
polyglot.locale(lang_code);
app.set('polyglot', polyglot);

Where locales/index.js is pretty simple:

exports.en = require('./en.js');
exports.de = require('./de.js');

And each locale file:

module.exports = {
  "nested": {
    "so": "cool"
  }
}

@saponifi3d
Copy link
Contributor

@christopherdupont i've done something very similar with polyglot, the difference is mainly in the portion to load the translations, but basically the same in the postInitialize (which is deprecated now, and should just be initialize)

// app/app.js
module.exports = BaseApp.extend({
  postInitialize: function() {
    this.polyglot = new Polyglot();
    ...
  },

  // This is called directly on the server so we can use Polyglot
  // during server rendering.
  setPhrases: function(phrases) {
    this.polyglot.extend(phrases);
  },

  // The `start` method only gets called in the client on pageload.
  start: function() {
    // This sets the phrases in the client-side so we can use Polyglot
    // during client rendering.  The phrases are accessible with
    // `this.get('phrases')` because in the middleware (below) we set
    // them as an app attribute. An app's attributes are serialized as 
    // JSON and bootstrapped to the client.
    this.setPhrases(this.get('phrases'));

    // If you have lots of phrases, you may as well free up some memory
    // because they will no longer be accessed directly from `this.get()`.
    this.unset('phrases');
    ...
  },
  ...
});

// server/middleware/initI18n.js
module.exports = function() {
  return function(req, res, next) {
    // Fetch phrases from API or cache based on req.
    // Example fake method:
    fetchPhrasesBasedOnReq(req, function(err, phrases) {
      if (err) next(err);

      // Set the phrases so they're usable on the server during
      // view rendering, etc.      
      req.rendrApp.setPhrases(phrases);

      // Now set them as app attributes so they get serialized and
      // bootstrapped onto the page as JSON so we can use them in
      // the client.
      req.rendrApp.set({phrases: phrases});

      next(err);
    });
  };
};

This allows us to only load the phrases for the specific local (which we detect in middleware), then set the phrases on the app for that instance. The request will pass that through as you described to the client-side then the start function is run on the client-side only, to load the translations into polyglot, where we unset it on the app, to reduce memory usage.

@zcei
Copy link

zcei commented Sep 30, 2014

👍 for this solution. I like the encapsulation.

I solved it nearly the same way, but didn't split up phrases & polyglot.

Due to the fact that it gets serialized at transport we have the skeleton and thus can say:
this.set('polyglot', new Polyglot(this.get('polyglot')));

Looks messy in the first place, but with proper annotation it becomes clear, that it avoids regenerating nested phrases and actually reuses the object, so no additional workload
(correct me if I missed something)

@saponifi3d
Copy link
Contributor

@zcei awesome solution, thanks for sharing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants