<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>Techno Barje</title>
  <link href="http://techno-barje.fr/atom.xml" rel="self"/>
  <link href="http://techno-barje.fr/"/>
  <updated>2011-11-17T17:29:22+00:00</updated>
  <id>http://techno-barje.fr/</id>
  <author>
    <name>Alexandre Poirot</name>
    
  </author>

  
  <entry>
    <title>Jetpack localization using YAML format</title>
    <link href="http://techno-barje.fr/post/2011/11/17/jetpack-localization-yaml/"/>
    <updated>2011-11-17T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2011/11/17/jetpack-localization-yaml</id>
    <content type="html">&lt;p&gt;In &lt;a href=&quot;http://techno-barje.fr/post/2011/10/31/jetpack-localization/&quot;&gt;a previous post&lt;/a&gt;, I&amp;#8217;ve described my first proposal for localization support in jetpack addons. I&amp;#8217;ve decided to change locale files format for &lt;a href=&quot;http://en.wikipedia.org/wiki/YAML&quot;&gt;YAML&lt;/a&gt; instead of JSON. During MozCamp event, folks helped me identifying some pitfalls with JSON:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No multiline string support.&lt;/strong&gt; Firefox parser allows multiline but it is not officialy supported! So that it will disallow third party tools to work properly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No easy way to add comments.&lt;/strong&gt; It is mandatory for localizers to have context description in comments next to keys to translate. As there is no way to add comments in JSON, it will end up complexifying a lot locale format.&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;Example&lt;/h1&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;French locale file in YAML format&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;17&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;18&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;19&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;20&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;21&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;22&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;yaml&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# You can add comments with `#`&#8230;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;Hello %s&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;Bonjour %s&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;# almost &#8230;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;hello_key&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;Bonjour %s&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# wherever you want!&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# For multiline, you need to indent your string with spaces&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;multiline&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;s&quot;&gt;&amp;quot;Bonjour&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;   &lt;span class=&quot;s&quot;&gt;%s&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# Plural forms.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# we use a nested object with attributes that depends on the target language&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# in english, we only have &amp;#39;one&amp;#39; (for 1) and &amp;#39;other&amp;#39; (for everything but 1)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# in french, it is the same except that &amp;#39;one&amp;#39; match 0 and 1&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# in some language like Polish, there is 4 forms and 6 in arabic&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# So that having a structured format like YAML,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# help us writing these translations!&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;pluralString&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;%s&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;telechargement&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;%s&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;telechargements&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# I need to enclode these strings with `&amp;quot;` because of %. See note after.&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;Addon code&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;javascript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// Get a reference to `_` gettext method with:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;l10n&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// These three forms end up returning the same string.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// We can still use a locale string in code, or use a key.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// And multiline string gets its `\n` removed. (there is a way to keep them)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello %s&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;alex&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hello_key&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;alex&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;multiline&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;alex&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// Example of non-naive l10n feature, plurals:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pluralString&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;0 telechargement&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pluralString&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1 telechargement&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pluralString&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;10 telechargements&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h1&gt;Advantages of YAML&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multiline strings are supported nicely / easy to read.&lt;/strong&gt; You do not need to add a final &lt;code&gt;\&lt;/code&gt; on all lines. As mulitiline is easier, localizers can use them more often and it will surely improve readability of locale files!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Structured data format.&lt;/strong&gt; we can use this power whenever it is needed. For example, when we need to implement complex l10n features like plural forms or any feature that goes beyond simple 1-1 localization. The cool thing if we compare to JSON is that even if we define structures, we keep a really simple format with no noise (like {, }, &amp;#8220;, &amp;#8230;).&lt;/li&gt;
&lt;/ul&gt;


&lt;br/&gt; 


&lt;p&gt;As nothing comes without any issues, here is what I&amp;#8217;ve found around YAML:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This format is not a Web standard. I don&amp;#8217;t think it makes much sense to avoid using it because of that. We are clearly missing a standardized format for localization in the web world.&lt;/li&gt;
&lt;li&gt;You may hit some issues when you do not enclose your strings with &lt;code&gt;&quot;&lt;/code&gt; or &lt;code&gt;&#8217;&lt;/code&gt;. For example, you can&amp;#8217;t start a string with &lt;code&gt;%&lt;/code&gt;, nor having a &lt;code&gt;:&lt;/code&gt; in middle of your string without enclosing it.&lt;/li&gt;
&lt;li&gt;Even if YAML is not a web standard, it has been formaly specified. And unfortunately, a handy feature becomes a pitfall for our purpose! Some strings are automatically converted. &lt;code&gt;Yes&lt;/code&gt;, &lt;code&gt;True&lt;/code&gt;, &lt;code&gt;False&lt;/code&gt;, &amp;#8230; are automatically converted to a boolean value. We can work around this in multiple ways, either by documenting it, or modifying the parser. The same solution apply here, you need to enclose your string with quotes.&lt;/li&gt;
&lt;/ul&gt;


&lt;br/&gt;&lt;br/&gt;


&lt;p&gt;Again, feedback is welcomed on &lt;a href=&quot;https://groups.google.com/group/mozilla-labs-jetpack/t/da50c6dac33b445b&quot;&gt;this group thread&lt;/a&gt; and you can follow this work in &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=691782&quot;&gt;bug 691782&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Jetpack localization</title>
    <link href="http://techno-barje.fr/post/2011/10/31/jetpack-localization/"/>
    <updated>2011-10-31T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2011/10/31/jetpack-localization</id>
    <content type="html">&lt;p&gt;I&amp;#8217;m going to describe the first proposal of localization support for Jetpack.
This approach uses gettext pattern and json files for locales.
It is the first step of multiple iterations. This one only allows retrieving localized string in javascript code.
We are going to give ways to translate files, mainly HTML files, through another iteration.
And we are about to offer an online tool to ease addon localization (like babelzilla website).&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s start by looking at a concrete example, then I&amp;#8217;ll justify our different choices.&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;French locale file&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;javascript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello %s&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Bonjour %s&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;hello_user&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Bonjour %s&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;Addon code&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;javascript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// Retrieve a dynamic reference to `_` gettext method with:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;l10n&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// Then print to the console a localized string:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello %s&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;alex&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// =&amp;gt; Prints &amp;quot;Bonjour alex&amp;quot; in french.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// Or, if we don&amp;#39;t want to use localized string in addon code:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hello_user&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;alex&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Why gettext?&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;It gives a way to automatically fetch localizable strings or ids from source code
by searching for &lt;code&gt;_(  )&lt;/code&gt; pattern.&lt;/li&gt;
&lt;li&gt;It allows to use either strings or IDs as value to translate.
It is obviously better to use IDs. Because locales will broke
each time addon developer fix a typo in the main language hard coded in the code.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;But we should not forget that the high level APIs is trying to
simplify addon development. So that it has to be really easy to translate a simple
addon that has only 2 JS files and less than 50 lines of code!
And the simple fact to mandatory require a locale file for the default language
appears like a big burden for such small addon.&lt;/p&gt;

&lt;p&gt;Having said that, I&amp;#8217;m really happy that gettext approach doesn&amp;#8217;t discourage, nor
makes it harder to use IDs, and so, if an addon developer build a big addon
or just want to take more time to use better pratice, he still can do it, easily!&lt;/p&gt;

&lt;h2&gt;Why JSON for locales?&lt;/h2&gt;

&lt;p&gt;We could have used properties files, like XUL addons. But this format has some
limitations that are not compatible with gettext pattern. Keys can&amp;#8217;t contain spaces
and are limited to ASCII or something alike, so that we can&amp;#8217;t put text in a key.&lt;/p&gt;

&lt;p&gt;So instead of using yet another specific format, I&amp;#8217;m suggesting here to use JSON.
JSON is really easy to parse and generate from both client and server side,
and I&amp;#8217;m convinced that it is simple enough to be edited with a text editor.
On top of that we can build a small web application to ease localization.&lt;/p&gt;

&lt;p&gt;In my very first proposal, I used a complex JSON object with nested attributes.
But it ends up complexifying the whole story without real advantage.
So I&amp;#8217;m suggesting now to use the most simple JSON file we can require:
one big object with keys being strings or id to translate and values being translated strings.
Then we will be able to use JSON features to implement complex localization features,
like plurals handling. So that values may be an array of plurals forms.&lt;/p&gt;

&lt;h2&gt;The big picture&lt;/h2&gt;

&lt;p&gt;Everything starts with one addon developer or one of its contributor.
If one of them want to make the addon localizable, they have to use this new localization module.&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;js&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;l10n&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;There is already multiple choices that has been made here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;_&lt;/code&gt; is not a &lt;em&gt;magic global&lt;/em&gt;. We need to explicitely require it.
This choice will simplify compatibility with other CommonJS environnements, like NodeJS.&lt;/li&gt;
&lt;li&gt;The name of the module itself is &lt;code&gt;l10n&lt;/code&gt; instead of &lt;code&gt;localization&lt;/code&gt; in order to ease the use of it.&lt;/li&gt;
&lt;li&gt;This module expose &lt;code&gt;_&lt;/code&gt; function on &lt;code&gt;get&lt;/code&gt; attribute in order to be able to
expose another methods. I&amp;#8217;m quite confident we will need some functions for plurals or files localization.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Then, they need to use &lt;code&gt;_&lt;/code&gt; on localizable strings:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;js&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;context-menu&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;cm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;My Menu Item&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;URLContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;*.mozilla.org&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Now, they have two choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use a string written in their prefered language, like here.
So that they don&amp;#8217;t have to create a locale file.&lt;/li&gt;
&lt;li&gt;use an ID. Instead of &lt;code&gt;_(&quot;My Menu Item&quot;)&lt;/code&gt;, we will use: &lt;code&gt;_(&quot;contextMenuLabel&quot;)&lt;/code&gt;.
But it forces to create a localization file in order to map &lt;code&gt;contextMenuLabel&lt;/code&gt; to &lt;code&gt;My Menu Item&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Then, either a developer or a localizer can generate or modify locales files.
Each jetpack package can have its own &lt;code&gt;locale&lt;/code&gt; folder.
This folder contains one JSON file per supported language.
Here is how looks like a jetpack addon:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;* my-addon/
  * package.json   # manifest file with addon name, description, version, &#8230;
  * data/          # folder for all static files
    * images, 
    * html files, 
    * &#8230;
  * lib /          # folder that contains all JS modules:
    * main.js      # main module to execute on startup
    * my-module.js # custom module that may use localization module
    * &#8230;
  * locale/       # our main interest!
    * en-US.json
    * fr-FR.json
    * en-GB.json
    * &#8230;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The next iteration will add a new feature to our command line tool,
that is going to generate or update a locale file for a given language by fetching localization strings from source code.
For example, the following command will generate &lt;code&gt;my-addon/locale/fr-FR.json&lt;/code&gt; file:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;sh&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cfx fetch-locales fr-FR
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;my-addon/locale/fr-FR.json&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;javascript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;My Menu Item&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;My Menu Item&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Finally, we need to replace right side values with the localized strings:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;javascript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;My Menu Item&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Mon menu&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;And build the final addon XPI file with:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;sh&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cfx xpi
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Any kind of feedback would be highly appreciated on &lt;a href=&quot;https://groups.google.com/group/mozilla-labs-jetpack/t/da50c6dac33b445b&quot;&gt;this group thread&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to follow this work,
subscribe to &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=691782&quot;&gt;bug 691782&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
</feed>

