Last night, I got application-wide localization working in my Polymer application. It is not real internationalization and localization—it only allows for a single application-wide localization, but it is a start. Tonight, I hope to use some of Dart's
intl
package to come up with something better. Specifically, I would like to be able to dynamically change the locale at runtime.There is an example of Polymer internationalization in the Dart repository. I am not quite following along with that, but it does prove invaluable.
Yesterday's solution relied on attributes and
<content>
tags to include information from other locales: <hello-you hello="Bonjour" done="Fin">
<p>Présentez-vous une expérience personnalisée incroyable!</p>
</hello-you>
Those attributes and <content>
are then included in the template as:<polymer-element name="hello-you"> <template> <div> <h2>{{hello}} {{your_name}}</h2> <p> <input value="{{your_name}}"> <input type=submit value="{{done}}!" on-click="{{feelingLucky}}"> </p> <p class=instructions> <content></content> </p> </div> </template> <script type="application/dart" src="hello_you.dart"></script> </polymer-element>As I mentioned, the attributes like
hello
and done
have to to hard-coded in the page for this approach to work. Instead, I want those properties to be dynamic getters.In the end, I do not even use the
intl
package, which seems useful for strings requiring parameters (numbers or dates). I find that I can achieve what I want with a Labels
class like:class Labels { var locale; Labels(this.locale); operator [](label) { var lookup; switch (locale) { case 'fr' : lookup = fr; break; default: lookup = en; } return lookup[label]; } static Map get en => { 'hello': 'Hello', 'done': 'Done', 'instructions': 'Introduce yourself for an amazing personalized experience!' }; static Map get fr => { 'hello': 'Bonjour', 'done': 'Fin', 'instructions': 'Présentez-vous une expérience personnalisée incroyable!' }; }The localized labels are included as static methods. An instance of the
Labels
class provides an []
lookup, switching the labels based on the current locale.The various getters in the Polymer can then be written as lookups of
Labels
:@CustomTag('hello-you') class HelloYou extends PolymerElement { // ... @published String locale = 'en'; HelloYou.created(): super.created(); String get hello => _labels['hello']; String get done => _labels['done']; String get instructions => _labels['instructions']; var __labels; get _labels { if (__labels == null) __labels = new Labels(locale); return __labels; } // ... }That still will not quite work if I wanted to allow a human to change the locale on the fly, but it allows the Polymer to change locales with a simple attribute:
<hello-you locale="fr"></hello-you>Which results in:
I will pick back up tomorrow trying to allow a human to hot swap locales. I would also like to come up with a contrived example to use for
intl
messages. I do not think that I will end up using them in Patterns in Polymer (there's not an easy JavaScript equivalent), but I misunderstood them badly enough tonight to confuse myself into thinking that I needed them. This seems a fine chance to understand what they really can do.Day #973
I played with this a while ago and like the approach using filters http://stackoverflow.com/questions/20323815/how-to-initialize-internationalization-for-a-polymer-element-before-it-loads-on/20377702#20377702
ReplyDeleteThat is pretty nice. The filters make the Polymer template self-documenting for which fields get i18n. I'll give that a try in a day or two. Thanks!
Delete