jueves, 17 de noviembre de 2016

Implementar multiidioma en una aplicación ASP.NET con Angular translate.

Cuando nuestros pacientes aprendían idiomas antiguamente a veces se veían apurados al cambiar de uno a otro y se notaba que tenían que refrescar el conocimiento.

Ahora se les exige que sean capaces de cambiar de un idioma a otro sin que se note.

Este post requiere conocimientos de Angular al menos a nivel básico, para adquirirlos basta con leer unos cuantos capítulos de esta web:

Primeros pasos con Angular

Al menos hay que leer lo suficiente como para tener claro lo que son los controladores, los módulos, la aplicación angular, los bindings a etiquetas, las directivas y los scopes, son conceptos realmente sencillos de comprender y que llevan mucho menos tiempo del que parece si ya se domina JavaScript, cosa que se da por sentada, por tanto se anima al lector a empaparse de ello para comprender mejor lo que se explica a continuación.

El otro modo, es el de toda la vida, el de copy/paste como un loro, pero bueno, allá cada cual.

Lo que se presenta en este artículo es una solución que quizás necesita retoques por supuesto, pero que funciona, que es lo importante.

En nuestro caso, el multiidioma lo implementamos en la master de la aplicación ASP.NET para que tenga efecto sobre cualquier página que pongamos incrustada.

Lo primero es insertar las referencias a angular y al js en el cual estará el código del programador (translateApp.js en este caso), es recomendable subir las referencias a una carpeta local del proyecto para evitar, si nuestras referencias son remotas, que pudieran afectar las posibles actualizaciones sin previo aviso:

    <script src="Scripts/angular.min.js"></script>
    <script src="Scripts/angular-translate.min.js"></script>
    <script src="Scripts/translateApp.js"></script>

Dentro de un div en la master que englobe a los asp:Contents se colocará un control de selección para el idioma, si se requiere imágenes u otra cosa, se hará lo equivalente para otro control:

       <div class="container body-content" ng-app="at" ng-controller="Ctrl">
            <div class="ng-scope">
                 <select ng-model="selectedLanguage" ng-change="selectLanguage()" ng-options="x for (x, y) in languages">
                 </select>
            </div>
            <asp:ContentPlaceHolder ID="MainContent" runat="server">
            </asp:ContentPlaceHolder>
        </div>

Explicando rápidamente el tag select de arriba, el selector tiene unas etiquetas de Angular para controlar su enlazado a datos ng-model, el evento al cambiar su valor, ng-change, que va a una función llamada selectLanguage() y una expresión para llenar sus opciones en ng-options.

Por supuesto, el div que lo engloba es el que contiene los tags de Angular para referenciar a la app de Angular y al controlador que contendrá el código para manejar todo el contenido dentro de ese div.

Ahora exponemos el contenido del archivo translateApp.js, donde se hace uso de la api translate de Angular:


var app = angular.module('at', ['pascalprecht.translate']);

app.config(function ($translateProvider) {
    $translateProvider.translations('English', {
        HelloLiteral: 'Hello',
        FirstParagraphLiteral: 'This is a paragraph.'
    });
    $translateProvider.translations('German', {
        HelloLiteral: 'Hallo',
        FirstParagraphLiteral: 'Dies ist ein Paragraph.'
    });
    $translateProvider.preferredLanguage('English');
});

app.controller('Ctrl', function ($scope, $translate) {
    $scope.languages = {
        English: 'English',
        German: 'German'
    };
    $scope.selectedLanguage = $scope.languages.English;
    $scope.selectLanguage = function () {
        $translate.use($scope.selectedLanguage);
    }
});

Tanto la configuración como el controlador de la app se puede encontrar en su estado básico en la web de angular translate, de donde se ha sacado el código, lo único reseñable en este caso es haber adaptado el código original, el cual venía preparado para un botón, a un control select.

Además se ha añadido la inicialización del select al preferredLanguage, en este caso mediante código lo cual no es lo más deseable, pero con algunas modificaciones puede detectarse automáticamente.

Dentro de cada función translations se incluirá un idioma donde se abarcan todas las etiquetas de los controles que hay en la interfaz para cada texto que llevará en ese idioma.

Por simple organización y comodidad, quizás sería deseable poner las etiquetas y los literales para cada idioma en archivos json separados por idioma, esto a gusto del consumidor.

Por último, ponemos los controles allá donde se desee en las páginas de la aplicación que hereden de la master, si no heredan de la master, se deberá declarar otro controlador para esa página.

En este caso no ha sido necesario, a continuación se presenta un ejemplo de controles en una página que hereda de la master:

<div>
    <h2 translate="HelloLiteral">Hello</h2>
    <p translate="FirstParagraphLiteral">This is a paragraph.</p>
</div>

La etiqueta translate que Angular translate define, servirá para enlazar cada control con su literal.

El resultado final:



No hay comentarios: