Blog multi-idioma con Jigsaw

Reny Ramos • August 10, 2020

jigsaw programming

La posibilidad de pasar de cero a tener un blog funcional, con una interfaz limpia y completamente estática, en cuestión de minutos, es algo realmente genial, sin embargo, la opción de multi-idioma es un punto bastante interesante y el cual es pasado por alto por la gente de Jigsaw, es por eso que es algo sobre lo que deseo plantear una opción viable en este post.

La idea principal es crear una copia del contenido por cada lenguaje y encargarse de el redireccionamiento, esta es una táctica con la cual experimente para la documentación en git, sin embargo le aplique algunos cambios y mejoras para ser usale en jigsaw y la adapte para blogs.

Debo aclarar que tomare como hecho que ya esta instalado y configurado el template de blog que trae jigsaw (del cual se habla en este link), que ya se compilo y esta en funcionamiento sin ningún problema, ademas de que el lector posee cierto conocimiento de programación, finalmente para facilitar un poco el proceso y la lectura procederé a separar en secciones.

Contenido estático

El multi-idioma para Index, About y Contact es la parte mas sencilla, para esto simplemente se creara una carpeta por cada idioma en la raíz de source con el formato \en y \es, luego procederemos a copiar los archivos en cada carpeta, por ultimo el archivo index.blade.php lo reemplazaremos con un sencillo script el cual se encargara de redirecionar la pagina al idioma que deseamos tener como base.

<script>
    window.location.href = "{{ $page->getPath() . '/en' }}"
</script>

Adicionalmente tenemos la opcion de hacer lo mismo con todas las paginas de contenido estático que estén en la raíz, la idea es que solo se pueda acceder a la versión con idioma.

Selector de idioma.

Aquí es donde comienza lo divertido, existen varias opciones pero me iré por la que me parece mas sencilla, 2 selects con los idiomas que se pueden seleccionar, uno para el menú responsive y otro para el menú para desktop, muy parecidos entre si pero con algunas diferencias claves, como estilo.

Responsive

<div class="md:w-1/6 px-1 mb-6 md:mb-0">
    <div class="relative">
        <select class="block appearance-none bg-gray-300 border border-gray-500 text-gray-800 py-2 px-2 pr-6 rounded focus:outline-none focus:bg-white focus:border-gray-400" id="idiom-select-r">
        <option value="en" {{ $page->get_lang() == 'en' ? 'selected' : ''}}>En</option>
        <option value="es" {{ $page->get_lang() == 'es' ? 'selected' : ''}}>Es</option>
        </select>
    </div>
</div>

Desktop

<div class="w-full md:w-1/2 px-1 mb-6 md:mb-0">
    <div class="relative">
    <select class="block appearance-none w-full bg-gray-100 border border-gray-300 text-gray-700 py-1 px-3 pr-8 rounded leading-tight focus:outline-none focus:bg-white focus:border-gray-300" id="idiom-select">
        <option value="en" {{ $page->get_lang() == 'en' ? 'selected' : ''}}>En</option>
        <option value="es" {{ $page->get_lang() == 'es' ? 'selected' : ''}}>Es</option>
    </select>
    <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
        <svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/></svg>
    </div>
    </div>
</div>

Y para el control de la lógica del cambio de idioma un pequeño script que se deberá anexar al layout.

<script>
    function updateLang() {
        let url = "{{ $page->getUrl() }}"
        let newlang = document.getElementById(this.id).value
        if ({{ $page->slug_has_lang() }}) {
            let lang = "{{ $page->get_lang() }}"
            url = url.replace('/' + lang ,'/' + newlang)
        } else {
            //Else (la pagina no tiene idioma y se lo agrego)
            url = url.replace("{{ $page->getPath() }}", '/' + newlang + "{{ $page->getPath() }}")
        }
        window.location.href = url
    }

    document.getElementById('idiom-select').addEventListener("change", updateLang, false)
    document.getElementById('idiom-select-r').addEventListener("change", updateLang, false)
</script>

Para aquellos que tengan experiencia con Jigsaw o que sean muy curiosos notaran un método que no viene por defecto {{ $page->get_lang() }}, este es un metodo personalizado que cree en el archivo de configuración, el cual se encarga de comprobar el idioma actual que esta seleccionado y retornarlo.

'get_lang'          => function ($page) {
    if ($page->getPath()[0] !== '/') {
        return $page->getPath()[0] . $page->getPath()[1];
    }
    return $page->getPath()[1] . $page->getPath()[2];
},

Posts Multi-idioma.

Con los post comenzaremos con una técnica parecida a la de los archivos estáticos, crearemos una carpeta por cada idioma que se desee soportar en el rot de source, tomando como base la siguiente nomenclatura _post_en y _post_es, como es de esperar, dentro de cada carpeta tendremos una copia de cada post en su idioma.

Dentro de config.php en el área de collection, procederemos crear una nueva collection por cada idioma de los post, los cuales seguirán esta nomenclatura.

'posts_es'      => [
    'author' => 'Reny Ramos', // Default author, if not provided in a post
    'sort'   => '-date',
    'path'   => 'es/blog/{filename}',
],
'posts_en'      => [
    'author' => 'Reny Ramos', // Default author, if not provided in a post
    'sort'   => '-date',
    'path'   => 'en/blog/{filename}',
],

Con estos cambios ya se debería tener la base para un blog multi-idioma bastante funcional, para el próximo post hablare sobre como configurar las categorías para ser multi-idioma y que solo muestren post en su idioma, y con algo de suerte también sobre un nuevo feature llamado de forma temporal "serie" con el cual estoy experimentando actualmente.