Adding multiple languages to a Windows Store app with Javascript and Angular

Leer este artículo en castellano aqui

Last thursday I could attend a debate organized by MSCoders Madrid user group, related with localization of apps in a web enfironment.

After the event I got interested in frontend localization with Javascript. As Karmacracy for Windows is a Javascript app, I decided to do some experimentation on localizing the user interface in the context of a Windows Store app, to be able to distribute it for other markets.

Detecting the system language

For a Windows Store app the first thing to do is to detect the sustem language. This can be archieved with the following piece of code:

var culture = Windows.System.UserProfile.GlobalizationPreferences.languages[0];
var language = culture.substr(0, 2);

The culture is the language that is currently being used for the UI, in culture format. For example for Spanish of Spain would be es-ES, for US English would be en-US, and for British English would be en-GB. To be able to change this order and deploy our app, we must go to the control panel:

Captura de pantalla 2014-09-15 00.29.43

In this example we only need the language, not the culture, so we are going to get a substring of the culture getting en, es, de, etc.

Adding angular-translate

Angular-translate is a module that allows us to define key-value pairs for each language and perform the translation according to the configuration. For installing it, if we don’t use a package manager such as bower, we must download the last package from github and add it to our project.

Once installed, we must add it to the configuration of our app, in the section we define external modules (in this case the module is pascalprechtr.translate).

var karmacracyApp = angular.module('karmacracyApp', [
    'ngRoute',
    'karmacracyControllers',
    'pascalprecht.translate'
]);

Finally, we configure the different languages by using the code we defined previously for getting the OS display language:

karmacracyApp.config(['$translateProvider', function ($translateProvider) {
    $translateProvider.translations('en', {
        'LOGIN': 'Log in',
        'LOGIN_USERNAME': 'User name',
        'LOGIN_PASSWORD': 'Password'
    });

    $translateProvider.translations('es', {
        'LOGIN': 'Inicia sesión',
        'LOGIN_USERNAME': 'Nombre de usuario',
        'LOGIN_PASSWORD': 'Contraseña'
    });

    var culture = Windows.System.UserProfile.GlobalizationPreferences.languages[0];
    var language = culture.substr(0, 2);

     $translateProvider.preferredLanguage(language).fallbackLanguage('en');
}]);

Also, in case the current language is not available, we set English by default

#Usage

For accessing our keys we don’t need any aditional configuration on our controllers, we just need to modify our views so they can access the localized information

<span class="loginMessage">{{ 'LOGIN' | translate }}</span>

If the language is set to English or other language not controlled, the result will be the following:

en

If the language is set to spanish, the result will be the following:

es

As it shows, is an easy way to localize our javascript apps for the Windows Store.

Recap and next steps

Angular-translate provides a simple way of localizing texts in our views and Windows provides the information we need for setting the current language of an app.

As an aditional step, we may try to localize winjs controls such as buttons, which work in a very different way. Angular-translate also supports loading the translations from a json files, an option that may be useful if we want to distribute those files for translation by 3rd parties.

Links

Agregando múltiples idiomas a una aplicación de Windows Store con Javascript y Angular

**Read this article in English here

El pasado jueves tuve la ocasión de asistir a una mesa redonda organizada por el grupo MSCoders relacionada con la localización de aplicaciones en entornos web.

Tras el evento, uno de los temas que más llamó mi atención fue la localización en la parte Javascript, y como tenía una aplicación ya en la Windows Store que usaba ese lenguaje, me pareció interesante intentar localizarla para poder ofrecerla en otros mercados.

Detectando el idioma del sistema

Para una aplicación Windows 8 el primer paso es detectar el idioma del sistema, y eso lo podemos hacer de la siguiente manera:

var culture = Windows.System.UserProfile.GlobalizationPreferences.languages[0];
var language = culture.substr(0, 2);

En este caso tomaremos la lista de lenguajes preferentes, y de esa lista obtendremos el primer elemento. Para poder cambiar el orden de los elementos y probar los diferentes lenguajes, podemos cambiarlo en el panel de control:

Captura de pantalla 2014-09-15 00.29.43

El resultado se muestra en formato cultura, es decir, español de España se mostraría como es-ES, e inglés de EEUU se mostraría como en-US. Para nuestro ejemplo inicial, solamente necesitamos el idioma, con lo cual hacemos un substring y obtenemos en o es respectivamente.

Agregando angular-translate

Angular-translate es un módulo de angular que nos permite definir de manera las claves y los valores para cada lenguaje, y realizar la traducción en función de la configuración. Para instalarlo, si no contamos con gestores de paquetes como bower, es tan sencillo como descargar el último paquete de github y agregarlo a nuestro proyecto.

Una vez instalado, tendremos que agregarlo a la configuración de nuestra app, en el apartado en el que definimos módulos externos en este caso pascalprecht.translate:

var karmacracyApp = angular.module('karmacracyApp', [
    'ngRoute',
    'karmacracyControllers',
    'pascalprecht.translate'
]);

Finalmente, configuramos los diferentes idiomas usando el código que hemos visto anteriormente para seleccionar un idioma acorde con el sistema operativo:

karmacracyApp.config(['$translateProvider', function ($translateProvider) {
    $translateProvider.translations('en', {
        'LOGIN': 'Log in',
        'LOGIN_USERNAME': 'User name',
        'LOGIN_PASSWORD': 'Password'
    });

    $translateProvider.translations('es', {
        'LOGIN': 'Inicia sesión',
        'LOGIN_USERNAME': 'Nombre de usuario',
        'LOGIN_PASSWORD': 'Contraseña'
    });

    var culture = Windows.System.UserProfile.GlobalizationPreferences.languages[0];
    var language = culture.substr(0, 2);

    $translateProvider.preferredLanguage(language).fallbackLanguage('en');
}]);

Además, en caso de que el sistema tenga un idioma no controlado, estableceremos el inglés por defecto.

Uso

Para acceder a nuestras claves no necesitamos realizar ninguna configuración adicional en nuestros controladores, solamente necesitamos modificar nuestras vistas para que accedan a la información localizada:

<span class="loginMessage">{{ 'LOGIN' | translate }}</span>

En caso de que tengamos el idioma establecido a inglés (o a cualquier idioma no controlado), se mostrará el siguiente resultado:

en

En caso de que el idioma esté establecido a español, el resultado será diferente:

es

Como se ve, es una manera sencilla de poder localizar nuestras aplicaciones en javsacript para Windows Store

Conclusiones y pasos adicionales

Angular-translate proporciona una manera sencilla de localizar textos en nuestras vistas, por otra parte, Windows proporciona, a través de su API, la información que necesitamos para saber en qué idioma mostrar una aplicación.

Un paso adicional sería localizar controles winjs como los botones, que funcionan de manera diferente. Por otra parte se podría sacar un fichero de traducciones fuera de la configuración en formato json, útil si queremos distribuir esos ficheros para su procesamiento.

Enlaces adicionales

Challenges developing Karmacracy for Windows 8

Update: The source code is available now at https://github.com/rlbisbe/karmacracy

Leer la versión en castellano de este artículo

Last April, after several months of development, and continuing the work with HTML, CSS and Javascript I was doing with RealPoll, I published Karmacracy, a Windows 8 app for the popular social network that looks like this:

upload1

The technology that lies behind is HTML + CSS + Javascript. The framework used was AngularJS with some WinJS features like the AppBar or flyouts. Except these two components, the goal was to get an app as portable as possible that could be then exported to platforms like Firefox OS.

Architecture

The architecture used includes partial views, controllers and services who serve as a link to share information between components:

Architecture

Each controller is associated with a view, and in this case we have three of them:

  • user: Displays information of current logged-in user
  • details: Display the details of a kcy
  • world: Displays the main screen, where we can share our link

There are also a couple of additional services that share information between controllers:

  • currentKcy: Allows to share the current kcy from the world view to the details view
  • karmacracyLogin: Allows to share the login status on the different controllers

Finally, a key component was the karmacracy.js library developed by Jorge del Casar, who has saved me a lot of development time by encapsulating the API calls easily.

Challenges

Developing this app has been very challenging, there were adaptations needed from AngularJS to run on a sandbox environment, a custom horizontal scroll was made, and also, the interaction with WinJS has been tough, let’s see a couple examples:

Horizontal scroll

One of the coolest things was to do a custom horizontal scroll that could be multiplatform, so after some research and try-and-error, the result looks nice:

The solution is extended more deeply on this article.

AngularJS with Windows Store

It turns out that making AngularJS to work on a sandbox environment we need to do some small changes to the library source code, in the methods where we inject HTML. Windows considers it a security leak, so we must tell it to ignore it. The solution is extended on this article

WinJS integration

For having details such as the back buttons, the flyouts or the app bar, we needed some integration with WinJS, which provides styles and interactions. The first thing we need is to add the references to WinJS on the main page:

    <link href="//Microsoft.WinJS.2.0/css/ui-light.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.2.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.2.0/js/ui.js"></script>

We also needed to call the «processAll» event from the controller for the styles and commands to start working. To do it, we wait until the page is active, and we make the call:

$scope.$on("$routeChangeSuccess", function (scope, next, current) {
          $scope.transitionState = "active";
          WinJS.UI.processAll();
});

Once the code is up and running we can add the AppBar, and assign the buttons an action ng-click and (if required) a style with ng-style

    <div id="appBar" data-win-control="WinJS.UI.AppBar" data-win-options="">
        <button ng-click="refresh(true)" data-win-control="WinJS.UI.AppBarCommand"
                data-win-options="{label:'Actualizar',icon:'refresh',
                section:'global',tooltip:'Actualizar'}"></button>

        <button ng-style="{'visibility': logged_in}" ng-click="share()" data-win-control="WinJS.UI.AppBarCommand"
                data-win-options="{id:'cmdCamera',label:'Compartir',icon:'reshare',
                section:'selection',tooltip:'Compartir'}"></button>
    </div>

Launching the flyouts is as easy as search for the control, and display it like we could do with jQuery:

var flyout = document.getElementById("contactFlyout").winControl;
flyout.show(main);

Finally, we can access preferences in a very similar way, in this case the call is performed from the app.js file, right after the routing and the controllers:

WinJS.Application.onsettings = function (e) {
    e.detail.e.request.applicationCommands.append(new Windows.UI.ApplicationSettings.SettingsCommand('privacy', 'Política de privacidad', function () {
        Windows.System.Launcher.launchUriAsync(new Windows.Foundation.Uri('http://rlbisbe.github.io/karmacracy/privacidad'));
    }));
};

WinJS.Application.start();

In this case, the goal was to show a privacy policy and redirect it to the web, but we can also use it as an internal link (for account configuration, for example).

Recap

This has been my first HTML5 app, the source code will be available soon on Github (and I’ll update the post when that occurs. Develop an app for Windows 8 is very, very easy but can be very challenging if you use a framework like angular.

I’ll keep refining the app while I read more and continue my training on this platform.