Cuando hablamos de web multi-idioma en asp.net es un tema resuelto gracias a los resources, pero para una SPA en Javascript existen diferente soluciones.

En estos días varias personas me preguntaron cómo trabajaba el tema de idiomas en una SPA, mi respuesta es que a día de hoy uso i18n.js  la cual es una librería para soporte a i18n en javascript combinándola con una librería de template “mustache” o “handlebars”.

En este ejemplo crearé un formulario multi-idioma usando Mustache para la vista(view) , el cual mostrara el nombre y el apellido y  un select (combobox) donde se puede seleccionar el idioma para verlo en español, ingles o chino.

Primero descargar las librerias que necesito:

I18njs http://i18njs.com/js/i18n.js

Mustache  https://github.com/janl/mustache.js

JQuery https://jquery.com/download/

La estructura  será la siguiente:

langs: contiene los jsons con las traducciones. (en.json, es.js, ch.json).
libs: las librerias (jquery, i18n y mustache)
appweb.js el archivo que contendrá la lógica.
index.html: contiene la view y el template de mustache , además de un select para elegir el idioma.

index.html

Agrego   las librerías descargadas al index.html y creo el contenedor div “app” de la aplicación y el template de mustache, llamado “welcome” con las propiedades que quiero visualizar y llenar con el binding desde mustache.

Para saber mas sobre la sintaxis y templates de mustache. https://github.com/janl/mustache.js

<div id="app" class="container">
</div>
<script id="welcome" type="x-tmpl-mustache">
        <div class="row">
            <h1>{{appname}}</h1>
        </div>
        <p>{{picklang}}</p>
        <select id="slang">
            <option value="df">{{df}}</option>
            <option value="ch">{{chinesse}}</option>
            <option value="es">{{spanish}}</option>
            <option value="en">{{english}}</option>
        </select>
        <div class="row">
            <div class="col-xs-12">
                <p>{{name}} {{myname}}</p>
                <p>{{lastname}} {{mylastname}}</p>
            </div>
        </div>
    </script>

langs:

En el directorio Langs creo los jsons especificando los tags que se mostrarán en la vista (view).

es.json:

{
    "values": {
        "lastname": "Apellido",
        "name": "Nombre",
        "appname": "Aplicacion",
        "picklang": "Seleccione un Idioma",
        "english": "English",
        "spanish": "Espanol",
        "chinesse": "奇诺",
        "df": "Default"
    }
}

ch.json:

{
    "values": {
        "lastname": "姓",
        "name": "名称",
        "appname": "应用程序名称",
        "picklang": "选择一种语言",
        "english": "English",
        "spanish": "Español",
        "chinesse": "奇诺",
        "df": "Default"
    }
}

Repito el proceso para cada idioma de la aplicación.

appweb.js

Esta es la lógica de la aplicación, defino dos variables apptemplate y userlang.

apptemplate: Guarda la view de mustache.
userlang: Guarda el objeto de i18njs que contendrá las traducciones.

var apptemplate;
var userlang;

Creo la función NavigatorLanguage para detectar el idioma del navegador y especificar uno.

function NavigatorLanguage() {
    if (window.navigator.language != undefined)
        return window.navigator.language;
    else
        return es;
}

Luego usando jquery creo la función “GetES” que carga el json y la asigno a userlang  con el objeto de i18n.

function GetES(callback) {
    $.ajax('langs/es.json').done(function(text) {
        userlang = i18n.create(text);
        callback(true)
    })
}

Creo el método RenderView que se encarga de renderizar la view de Mustache, recibiendo por parametro el template y el viewmodel e internamente llamando el método Mustache.render para actualizar la vista.

function RenderView(template, vm) {
    return Mustache.render(template, vm);
}

Para enviar los datos a la view creo el método bindview() en el cual enviare el viewmodel (json) que espera el método RenderView junto al template.

function bindview(vm) {

    var vm = {
        name: userlang("name"),
        myname: "Dany",
        lastname: userlang("lastname"),
        mylastname: "Paredes",
        appname: userlang("appname"),
        picklang: userlang("picklang"),
        english: userlang("english"),
        spanish: userlang("spanish"),
        chinesse: userlang("chinesse"),
        df: userlang("df")
    }

    document.getElementById('app').innerHTML = RenderView(apptemplate, vm);
}

Ahora toca el proceso de saber el lenguaje del usuario y a partir de ahí cargar el json, llamar los métodos de binding y render de la view.

function showview(lang) {
    console.log(lang)
    apptemplate = document.getElementById('welcome').innerHTML;
    var lang = lang || NavigatorLanguage();
    switch (lang) {
        case "es":
            GetES(bindview);
            break;
        case "en":
            GetEN(bindview);
            break;
        case "ch":
            GetCH(bindview);
            break;
        default:
            GetEN(bindview);
    }
}

En el función document.ready() registramos el evento para cuando el usuario cambie el lenguaje y tomar el idioma s seleccionado para enviarlo a la  función showview.

$(document).ready(function() {
 $(document.body).on('change', '#slang', function() {
         showview(this.value)
     });
     showview()
})

Código de ejemplo https://github.com/danywalls/multi-idioma-con-i18njs-y-mustache

Demo  http://i18mustacheejemplo.surge.sh/ 

Gracias a @oriolpuigbuil por el feedback!

Imagen  by Freepik

Happy i18n!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *