Thursday, December 19, 2013

Supplementing Jekylls missing I18n support with Ant

Jekyll has no native support for multilingual websites, and while there exists a plugin adding that support, that does not help if your site is built on Github Pages. You could build your site locally, and push the rendered site to Github Pages, but here is an alternative solution:
In fact, if you only want to translate some strings to a couple of languages, and all translations are 100% complete, Jekyll can handle this use case easily. You put your translation data into a YAML file, e.g. named msg.yml in the _data directory

en:
  hello_world: Hello world
de:
  hello_world: Hallo Welt
fr:
  hello_world: Bonjour le monde
 
Then the following lines in your template, will assign the array for the page language to an array named msg:

{% capture pagelang %}{% if page.lang %}{{page.lang}}{% else %}en{% endif %}{% endcapture %}
{% assign msg = site.data.msg[pagelang]  %}
 
in your page's front matter, you simply declare the lang, and make use of the msg array:

---
layout: neu
lang: en
---
{{msg.hello_world}}

This solution fails if your translations are partial, and you want to fall back to the default language, if a certain string is missing, unless you programm this fallback into  all your references to the msg array:

{% if msg.hello_world %}{{msg.hello_world}}{% else %}{{site.data.msg.en.hello_world}}{% endif %}

Since this would make your content difficult to read and maintain, I came up with the following idea of preprocessing the content.

My content now resides in a file content.html.tmpl, where I use a special marker for localized content:

{{t.hello_world}}
 
and I let a ant task copy the template and replace this marker with the full-blown jekyll syntax for falling back to the default locale:

<project default="localize" name="MyWebsite">
  <target name="copy">
    <copy encoding="utf-8" file="content.html.tmpl" overwrite="true" tofile="content.html"/>
  </target>
  <target depends="copy" name="localize">
    <replaceregexp
        byline="true"
        match="\{\{t\.(.*?)\}\}"
        replace="{% if msg.\1 %}{{msg.\1}}{% else %}{{site.data.msg.en.\1}}{% endif %}">
      <fileset dir=".">
        <include name="content.html"/>
      </fileset>
    </replaceregexp>
  </target>
</project>

Put this xml into a file called build.xml, and then simply invoking ant will execute the task. This task currently only handles as an example one single file, but ant could easily handle applying the same transformation to a whole fileset.

No comments:

Post a Comment