Wednesday, February 19, 2014

Getting Started with i18next and Polymer


The two chapters that I would like to include in the 1.1 edition of Patters in Polymer are i18n and deployment considerations. I thoroughly enjoyed my recent foray back into the Dart side of things, but I think tonight I need to spend a little time with a JavaScript solution to better understand one of those chapter topics.

So I revisit my old, hand-coded i18n solution by first installing i18next via Bower:
➜  js git:(master) ✗ bower install --save i18next
...
bower i18next#~1.7.2           install i18next#1.7.2

i18next#1.7.2 bower_components/i18next
My current solution has Polymer do the heavy lifting. Specifically, my Polymer reads the specified localization JSON files and replaces values like {{hello}} and {{done}} with the appropriate value from the current locale:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="hello-you-en.json">
<link rel="import" href="hello-you-fr.json">
<link rel="import" href="hello-you-es.json">
<polymer-element name="hello-you" attributes="locale">
  <template>
    <div>
      <h2>{{hello}} {{your_name}}</h2>
    </div>
    <p>
      <input value="{{your_name}}">
      <input type=submit value="{{done}}!" on-click="{{feelingLucky}}">
    </p>
    <!-- ... -->
  </template>
  <script src="hello_you.js"></script>
</polymer-element>
With i18next already installed, I start by adding it to my Polymer with a script tag at the end of the <template>:
<link rel="import" href="../bower_components/polymer/polymer.html">
<polymer-element name="hello-you" attributes="locale">
  <template>
    <!-- ... -->    
    <script type="text/javascript" src="../bower_components/i18next/i18next.js"></script>
  </template>
  <script src="hello_you.js"></script>
</polymer-element>
When I reload the page containing the Polymer, I see that it is now 404ing on /locales/en-US/translation.json, so I add that as:
{
  "app": {
    "hello": "Hello",
    "done": "Done",
    "how_many": "How many?",
    "instructions": "Introduce yourself for an amazing personalized experience!"
  }
}
Then, in my Polymer's ready, I run the i18n initialization:
Polymer('hello-you', {
  // ...
  ready: function() {
    setTimeout(function(){
      i18n.init(function(t) {
        $(".app").i18n();
      });
    }, 500);
    // ...
  }
  // ...
});
Unfortunately, I cannot quite figure out how to make jQuery find the app class in the Polymer's shadow DOM. I am able to configure this by explicitly setting the Polymer bound variables instead:
  ready: function() {
    var that = this;

    setTimeout(function(){
      i18n.init(function(t) {
        $(".app").i18n();
        that.hello = t('app.hello');
        that.done = t('app.done');
        that.how_many = t('app.how_many');
        that.instructions = t('app.instructions');
      });
    }, 500);
    // ...
  }
Which results in an English localized version of the <hello-you> Polymer:



That's really no different from the approach that I already took with raw Polymer except that I was previously able to leverage some of the Polymer platform to avoid the timeout (which prevents the code from running before i18next is loaded). Still, even if I cannot get jQuery working with the shadow DOM, there is still power to be explored in i18next (dates and plural forms). I will pick back up with that tomorrow.

Day #1,031

No comments:

Post a Comment