Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Include different file in Jekyll depending on the locale

I'm trying to create my first Jekyll website and I'm encountering a problem designing the i18n part.

The different articles will be totally rewritten for each language, so each one will be a different post, no problems here. I actually have more difficulties with the text in my layout / includes.

Typically, for the menu, I was thinking doing something along these lines:

{% capture menu_location %}menu.{{ lang }}.html{% endcapture %}
{% include menu_location %}

like suggested here. But this gives me the following error :

Included file 'menu_location' not found in _includes directory

Is it possible to use a variable for the include tag ? Do you have any other idea how I can do this ?

Thanks !

PS: Even if I have only 3 languages in mind for the moment, I won't do it with an if / elseif / else syntax ;)

like image 516
krtek Avatar asked Jun 17 '11 23:06

krtek


1 Answers

What you are trying to do isn't possible without modifying Jekyll. The include filter they defined treats its parameter as a string, not as an expression.

I've created a couple bilingual sites with Jekyll in the past. I found that the cleanest solution was often storing locale-dependant variables inside _config.yml, and reference it when needed.

# _config.yml
...
locales:
  en:
    welcome_message: "Welcome to my site"
    ...
  es:
    welcome_message: "Bienvenido a mi sitio"

For every page I render, I need to know its locale. The simplest way of doing that is adding a locale field on the top yaml that page:

---
# a page or post (for example index.html)
...
locale: en
---

You can then get the current page locale by doing page.locale.

If you have divided your site in folders (/en/ for english, /es/ for spanish, and so on, you can use the page url to calculate the locale, so that you don't need to specify the locale on each page:

{% capture locale %}{{ page.url | truncate: 3, "" | remove: "/" }}{% endcapture %}
{% if locale == "" %}{% assign locale = "en" %}{% endif %}

For a page like /en/blog/, locale will be 'en'; for /fr/le-blog, it will be 'fr'. You will have to use that line in all the layouts and includes that need to use the locale, though.

You can then get localized texts like this:

{{ site.locales[locale].welcome_message }}

Or, if you prefer page.locale:

{{ site.locales[page.locale].welcome_message }}

Menus are the same; you can generate them from _config.yml, too:

# _config.yml
...
locales:
  en:
    nav:
    - text: Welcome
      url: /en/welcome
    - text: Blog
      url: /en/blog
      layout: post
    ...
  es:
    nav:
    - text: Bienvenido
      url: /es/bienvenido
    - text: Blog
      url: /es/blog
      layout: post
    ...

Then you can have a single menu.html that generates the right menu depending on the page locale:

{% capture locale %}{{ page.url | truncate: 3, "" | remove: "/" }}{% endcapture %}
{% if locale == "" %}{% assign locale = "en" %}{% endif %}
<nav>
<ul class="nav">
{% for link in site.locales[locale].nav %}
  {% assign current = nil %}
  {% if page.url == link.url or page.layout == link.layout %}
    {% assign current = 'current' %}
  {% endif %}

  <li class="{% if forloop.first %}first{% endif %} {{ current }} {% if forloop.last %}last{% endif %}">
    <a class="{{ current }}" href="{{ link.url }}">{{ link.text }}</a>
  </li>
{% endfor %}
</ul>
</nav>

For using ´page.locale´ instead of ´locale´, just remove the first two lines and replace site.locales[locale].nav by site.locales[page.locale].nav

I hope this helps.

Regards!

like image 121
kikito Avatar answered Oct 17 '22 08:10

kikito