Jekyll i18n

Featured image

Jekyll & multi-language sites

How are you guys doing? I’ve been building this blog to make it multilingual and I wanted to share with you how the process went in case you ever need or are tempted to build something like this with Jekyll.

There is quite a lot of material going around, with and without plugins, but there wasn’t much clarity, among several other aspects that I tried and didn’t work as I expected, plus some disadvantages of using plugins for this kind of functionality that then don’t behave as expected once deployed. So here we go with the implementation without plugins!

To keep in mind the stack I use is #Jekyll, #Liquid for templating, #RubyGems for packages and everything running on the #Ruby terminal.

enter image description here

Small intro to Jekyll

enter image description here To set up a blog or static site you will need to install Ruby.

Once installed, run the following commands to configure Jekyll fresh:

$ gem install bundler jekyll
~ $ $ jekyll new my-awesome-site
~ $ cd my-awesome-site
~/my-awesome-site $ bundle exec jekyll serve
# => Now browse to http://localhost:4000

For more documentation and details here!

What is i18n?

“It is common practice in the English language (especially in the computer field) to abbreviate internationalization with the numeronym “i18n”. This is because there are 18 letters between the first i and the last ene of the word. The same applies to localization, which is abbreviated to “L10n””.

In short, whenever we mention i18n or internationalization, we are referring to the fact of translating our content into N languages.

enter image description here

Jekyll

We start with skaffolding, very similar to what Jekyll already provides from scratch, the idea of organizing the divisions by language is subjective and my suggestion is the following, assuming a Spanish and English case:

    _posts
    	en
    		post1.md
    		post2.md
    	es
    		post1.md
    		post2.md

_config.yml

We set these new paths and configure them in our config as follows:

    defaults:
        - scope:
        path: '_posts/en
        type: 'posts
        values:
        'permalink: 'en'
        language: en
        - scope:
        path: '_posts/en'
        type: 'posts'
       values:
        permalink: 'en'
        language: en
        - scope:
        path: '_posts/en'
        type: 'posts'
        values:
        permalink: 'en/:title'
        language: en
        - scope:
        path: '_posts/en'
        type: 'posts'
        values:
        permalink: 'en/:title'
        language: en

As we can see above, the idea is to configure the paths relative to the languages that respect the structure we set up. The most important points to note are the following:

In addition to this, in our index.html and index.markdown files:

    ---
    layout: home
    permalink: en
    layout: home
    permalink: es
    ---

Liquid: i18n inside templates

Now here it comes the fun part to manage these languages on our views. Using Liquid, which is an open source templating engine from Shopify. If you used any engine like Twig or Smarty you’ll be friends in no time.

enter image description here

Language selector

    {% assign url_language = page.url | split: "/" %}

    <div  class="languages">
        <a  class="languages__link {% if url_language[1] == 'en' %} highlight-language {% endif %}"  href="/en">English</a>
        <a  class="languages__link {% if url_language[1] == 'es' %} highlight-language {% endif %}"  href="/es">Español</a>
    </div>

Filtered posts

Here we are going to filter the posts we display, so that only those that meet the language condition according to the url are displayed:

{% assign url_language = page.url | replace:’/’,’’ %} {% assign posts = site.posts | where_exp:”post”,”post.language == url_language “ %} {% for post in posts %} … {% endfor %}

And in the case of other filters that exist for other conditions, we can add the language filter:

{% assign next_posts = site.posts | where_exp:”post”,”post.is_generated != true” | where_exp:”post”,”post.path != page.path” %} {% assign url_language = page.url | split: “/” %} {% assign locale_next_posts = next_posts | where_exp:”post”,”post.language == url_language[1] “ %} {% assign shuffled_array = locale_next_posts | shuffle %} {% for post in shuffled_array limit:3 %} … {% endfor %}

Bonus!

enter image description here

Translations.yml

In case you want to translate not only posts, but also .yml configurations for texts that cross the site, it is also possible! Example:

    translations:
        text:
        new_post: "New Post"
        see_also: "See also"
        search: "Search"
        author: "Author"
        share: "Share"
        comments: "Comments"
        button:
        read_now: "Read Now"
        share_on_twitter: "Share on Twitter"
        share_on_facebook: "Share on Facebook"
        pagination:
        page: "Page"
        of: "of"
        next_page: "Next Page"
        next_post: "Previous Page"

Redirects

There are several ways to redirect your index to one of these default languages, one of the simplest (that also works with Github pages) is to install the gem ‘jekyll-redirect-from’ more info here

We add in _config.yml the new plugin and add it to the whitelist:

plugins:
  - jekyll-redirect-from

whitelist:
  - jekyll-redirect-from

Finally we create an index.md where we are going to set the paths that we want to redirect to our home:

title: home
redirect_from:
  - /

References of a blog that finally helped me to achieve these changes without the need of plugins here!