5 min to read
Jekyll i18n
Sitios multilenguajes - Jekyll
Buenasss! como andan?? Estuve armando este blog para que sea multilenguaje y quería compartir con ustedes como fue el proceso por si alguna vez necesitan o se ven tentados de armar algo asi con Jekyll.
Hay bastante material dando vueltas, con y sin plugins, pero no había mucha claridad, entre otros varios aspectos que probé y no funcionaron como esperaba, además de algunas desventajas que presenta el hecho de usar plugins para este tipo de funcionalidad que luego no se comportan como se espera una vez que se deployan.
Así que ahi vamos con la implementación sin plugins! Para tener en cuenta el stack que utilizo es #Jekyll, #Liquid para templating, #RubyGems para paquetes y todo corriendo sobre la terminal de #Ruby.
Mini intro a Jekyll
Para armar un blog o sitio estático vas a necesitar instalar Ruby Una vez instalado, ejecutas los siguientes comandos para configurar Jekyll bien 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
Para más documentación y detalles acá!
Qué es i18n?
“Es una práctica común en el idioma inglés (sobre todo en el ámbito de la computación), abreviar internationalization con el numerónimo “i18n”. Ello se debe a que entre la primera i y la última ene de dicha palabra hay 18 letras. Lo mismo sucede con localization, que se abrevia “L10n””
dicho en criollo cada vez que mencionamos i18n o internacionalización nos referimos al hecho de traducir nuestros contenidos a N idiomas.
Jekyll
Arrancamos con el skaffolding, muy similar a lo que Jekyll ya proporciona from scratch, la idea de organizar las divisiones por idioma es subjetiva y mi sugerencia es la siguiente, suponiendo un caso español e inglés:
_posts
en
post1.md
post2.md
es
post1.md
post2.md
_config.yml
Seteamos estos nuevos paths y los configuramos en nuestro config de la siguiente forma:
defaults:
- scope:
path: '_posts/es'
type: 'posts'
values:
permalink: 'es'
language: es
- 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/es'
type: 'posts'
values:
permalink: 'es/:title'
language: es
Como vemos arriba, la idea es configurar los paths relativos a los idiomas que respeten la estructura que armamos. Lo más importante a destacar son los siguientes puntos:
- Path referirá a la ubicación real de la carpeta donde se encuentran los posts y su subcarpeta de idioma
- Permalink referirá a la url que necesitamos que se arme en base a nuestra estructura. En este caso, :title es un placeholder para dinámicamente apuntar las url a los nombres de cada post automáticamente.
- Y último pero no menos importante, al principio en defaults, algo que no encontré en otros blogs y me parece importante, es poder setear la url raíz para que también se pueda traducir, es decir, en la ruta del dominio tener por ej /en o /es para poder apuntar la home a cada idioma respectivamente, sin haber seleccionado un post para leer.
Sumado a esto, en nuestro index.html e index.markdown
---
layout: home
permalink: en
layout: home
permalink: es
---
Liquid: i18n inside templates
Ahora queda la parte divertida para gestionar estos idiomas desde lo que visibilizamos. Usando Liquid, que es un motor de templating open source de Shopify. Si usaste algun motor como Twig o Smarty te vas a hacer amigo en un abrir y cerrar de ojos.
Selector de idiomas
{% 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>
Filtrado de posts
Aquí vamos a filtrar los posts que mostramos, para que sólo se muestren aquellos que cumplan con la condición del idioma según la url:
{% assign url_language = page.url | replace:'/','' %}
{% assign posts = site.posts | where_exp:"post","post.language == url_language " %}
{% for post in posts %}
...
{% endfor %}
Y en el caso de otros filtrados que existan por otras condiciones, podemos sumar el filtro de idioma:
{% 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!
Translations.yml
En caso de querer traducir no sólo a nivel posts, sino a nivel configuraciones de .yml para textos que cruzan el sitio, también es posible! Ejemplo:
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
Hay varias formas de redireccionar tu index hacia alguno de estos idiomas por defecto, una de las mas simples (que tambien funciona con Github pages) es instalando la gem ‘jekyll-redirect-from’ mas info aca
Agregamos en _config.yml el nuevo plugin y lo agregamos a la whitelist:
plugins:
- jekyll-redirect-from
whitelist:
- jekyll-redirect-from
Finalmente creamos un index.md donde vamos a setear los path que queremos que redireccionen a nuestra home:
title: home
redirect_from:
- /
Referencias de un blog que me sirvió finalmente para lograr todos estos cambios sin necesidad de plugins aquí!