Globalización

globalizacion
Globalización

Definimos la globalización como la necesidad de desarrollar o adaptar una aplicación para internacionalizarla, ya sea por motivos culturales, o para la integración en nuevos países.

Hay que establecer cuantas culturas queremos referenciar, ya que es un trabajo laborioso que implica tener en mente las culturas a las que nos queremos dirigir. Por defecto en nuestra aplicación se dirige a nuestra cultura o región local, al implementar la globalización en nuestra aplicación, cambiara dinámicamente dependiendo de la elección cultural del usuario.

Interfaz
Interfaz de usuarios

Diseño de la interfaz de usuario

En primer lugar, como programadores tenemos que pensar en cómo diseñar una interfaz con todos los datos, formularios y recursos que queremos referenciar con la cultura. Como consecuencia, esto implica la serialización de formatos de fecha, monedas, y la capacidad de deserializar estos datos en nuestro sistema sin provocar problemas de excepciones gracias a la referencia cultural, ya que no afectan ni al código ni al diseño.

¿En qué estándar se basa la aplicación para cambiar de idioma?

estandar
Estándar ISO 639-1

La aplicación reconoce la taquigrafía internacional de códigos que nos ofrece el estándar de la ISO 639-1, estos códigos se usan para identificar los idiomas.  Ejemplo:

  • ja, es el código para Japón.
  • es, es el código para España.
  • zh, es el código para Chino.

Estos códigos pueden ir seguidos de una etiqueta(Tag) regional, que especifican la región del idioma habiendo diferencias en sintaxis de formatos de fecha, monedas, traducciones, etc. Ejemplo:

  • El código para francés canadiense es fr-CA.
  • El código para ingles australiano es en-AU.

Esta información sobre los códigos de idioma podemos verlos en el estándar de ISO 693: https://es.wikipedia.org/wiki/ISO_639-1 que va junto con el estándar de  etiquetas de idioma IETF: https://es.wikipedia.org/wiki/C%C3%B3digo_de_idioma_IETF.

Cabecera de Http en navegadores

cabecerahtml
Cabecera Http Accept Language

Las cabeceras de HTTP se envían desde la mayoría de navegadores, que contienen los parámetros que son una lista de idiomas definidos en la configuración del navegador. Por lo general, la primera opción es la principal y es enviada automáticamente por los navegadores.

El parámetro opcional de q=, se refiere a la calidad o peso de la traducción estimada por el usuarios, dependiendo de si le interesa una mejor calidad o peso, mayor o menor.

Dentro de nuestra aplicación MVC, podemos usar la propiedad Request.UserLanguages[] para ver la lista de idiomas soportados por la aplicación.

Nuevo proyecto implementando globalización

Para nuestro ejemplo, vamos a crear una aplicación con un formulario y una cabecera principal con lo siguiente: las etiquetas y descripciones del formulario se traducirán automáticamente, mostraremos en la parte inferior la fecha actual del sistema traducido con la cultura seleccionada, y la moneda formateada.

Veremos dos métodos para integrar las referencias a los recursos globales de cultura, tanto en la vista con @Razor, como en el controlador(Controller), accediendo a los recursos globales.

Creación del proyecto

La aplicación la vamos a crear con Visual Studio 2017, el proyecto será una aplicación ASP.NET Web Application (.NET Framework) llamada Globalización.

Los idiomas que vamos a globalizar serán el inglés y el japonés, para crear el proyecto tenemos que siguientes pasos:

Abrimos la aplicación con Visual Studio 2017 y creamos un nuevo proyecto seleccionado la opción de File -> New Project -> Web -> ASP.NET Web Application (.NET Framework) donde llamamos al proyecto, «Globalización».

tutorial1
Creación de proyecto

Ahora seleccionamos una plantilla Empty y con las referencias sobre MVC y le pulsamos sobre «OK».

tutorial2
Plantilla

Ahora vamos a proceder a crear un Controller, Sobre la carpeta Controllers hacemos Click derecho ->Add ->Controller llamado “CulturaController.cs” que mas tarde completaremos.

Código:

    // GET: Cultura
    public ActionResult Index()
    {
        return View();
    }

Para crear nuestro formulario, necesitaremos una clase modelo de Cliente, para poder tratar los datos. Hacemos Click derecho ->Add ->Classllamado “Cliente.cs” en la que tendremos las siguientes propiedades: nombre, apellido, email, dirección, cp, contribución y comentario.

Código:

public class Cliente
{
    [Required]
    public String Nombre { get; set; }
    [Required]
    public String Apellido { get; set; }
    [Required]
    public String Email { get; set; }
    [Required]
    public String Direccion { get; set; }
    [Required]
    public int CP { get; set; }
    [Required]
    public int Contribucion { get; set; }
    public String Comentario { get; set; }
}

Ahora vamos a proceder a crear una carpeta de recursos global, aquí es donde tendremos nuestros recursos .resx donde tendremos las traducciones de las culturas. Sobre el proyecto, hacemos Click derecho ->Add ->Add ASP.NET Folder ->App_GlobalResources.

tutorial3
Carpeta de recursos globales

Ahora sobre esta carpeta hacemos Click derecho ->Add ->Resources File llamado “Cultura.resx”, sobre este recurso, estableceremos la cultura principal de la que sacaremos los valores de las referencias, vamos a crear las siguientes referencias:

  • Name: nombre de la referencia.
  • Value: valor de la referencia.
tutorial4
Recurso Cultura predeterminado (castellano)

Aquí tendremos todas las referencias sobre el formulario, las imágenes y comentarios que referenciaremos en nuestra vista(View) y controlador(Controller).

A continuación vamos a crear las referencias para japonés en inglés, para ello debemos crear de nuevo un recurso hacemosClick derecho ->Add -> Resources File llamado “Cultura.ja.resx” y “Cultura.es.resx”. Los códigos ja y en hacen referencia por código a los idiomas, los cuales serán seleccionados dependiendo de la cultura que recojan uiCulturey Culture sobre la aplicación.

Recurso con traducciones en inglés.“Cultura.en.resx”

tutorial5
Recurso Cultura en inglés

Recurso con traducciones en japonés.“Cultura.ja.resx”

tutorial6
Recurso Cultura en japonés

Por último vamos a ir al archivo de configuración Web.Config para implementar la globalización para la aplicación, sobre la etiqueta(tag) de system.web introducimos lo siguiente:

<globalization culture="auto" uiCulture="auto" enableClientBasedCulture="true" />

Con este código ahora la aplicación es capaz de reconocer y cambiar la cultura de la aplicación e interfaz.

Diseño del controlador(Controller) 

Ahora vamos a proceder a completar el controlador de CulturaController.cs, sobre este controlador(Controller)tendremos dos métodos sobre la página Index, que serán Get y Post.

Sobre el método Get, vamos a recibir la cadena de cultura y establecerla como la cultura principal aparte de la fecha actual formateada.

Finalmente, sobre el método Post, recibiremos el modelo(Model) de cliente donde mostraremos un mensaje de agradecimiento con la donación formateada con la moneda formateada, al igual que en el método Get, vamos a recibir la cadena de cultura y establecerla como la cultura principal para mantenerla en el método Post.

Código de método Get:

    // GET: Cultura
    public ActionResult Index(String cultura)
    {
        if (cultura is null)
        {
            cultura = Thread.CurrentThread.CurrentUICulture.ToString();
        }
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultura);
        Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultura);
        ViewBag.Fecha = DateTime.Today.ToLongDateString().ToString(Thread.CurrentThread.CurrentCulture);
        return View();
    }

Recibimos la cultura y comprobamos si es null, si lo es establecemos la cultura como la actual predeterminada de la aplicación. Establecemos la cultura principal de la aplicación y de la interfaz de usuario con el método Thread.CurrentThread.CurrentCulture y Thread.CurrentThread.CurrentUICulture, donde les establecemos la cultura específica con el método CultureInfo.CreateSpecificCulture(cultura), donde se le pasa el código de la cultura con los valores en, es, ja, etc.

Por último vamos a formatear la fecha en un ViewBag con el método DateTime.Today.ToLongDateString().ToString(“Cultura actual”), donde le pasamos en el ToString() la cultura actual con la propiedad de Thread.CurrentThread.CurrentCulture, así nos lo formatearía al idioma establecido.

Código de método Post:

    // POST: Cultura
    [HttpPost]
    public ActionResult Index(String cultura, Cliente cliente)
    {
        if (cultura is null)
        {
            cultura = Thread.CurrentThread.CurrentUICulture.ToString();
        }
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultura);
        Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultura);
        ViewBag.Agradecimiento = Resources.Cultura.Agradecimiento+" "+cliente.Nombre;
        ViewBag.Donacion = String.Format(Thread.CurrentThread.CurrentUICulture, "{0:C}", cliente.Contribucion);
        return View(cliente);
    }

En el método Post recibiremos el modelo de la clase Cliente y lo enviaremos a la vista, al igual que el método Get, volveremos a establecer la cultura principal.

Para acceder a la traducción del ViewBag de agradecimiento con un mensaje para el usuario, tenemos que acceder a los recursos mediante Resources.Cultura.Agradecimiento, donde Resources buscaría en la carpeta global los recursos de Cultura y cogemos el valor de la referencia de Agradecimiento. Ahora cogería automáticamente la traducción dependiendo de la cultura seleccionada y le concatenamos el nombre del usuario accediendo a la clase Cliente y su propiedad Nombre con cliente.Nombre.

Por último, vamos a crear un ViewBag para la cantidad donada donde la formatearemos con su respectiva moneda de cada cultura con el siguiente método:

String.Format(“cultura actual”, «{0:C}»,cliente.Contribucion), donde le pasamos la cultura actual con la propiedad de Thread.CurrentThread.CurrentCulture, la codificación “{0:C}”, establece que el formato C se refiere a la moneda y 0-99 para la precisión. Como último dato le pasamos la contribución del cliente que contiene la cantidad de dinero donado a formatear y la guardaremos en ViewBag.Donacion.

Diseño de la vista(View) con el formulario

Vamos a la plantilla dentro de Shared -> _Layout.cshtml y vamos a crear un contenedor de navegación con las imágenes y ActionLink donde enviaremos al controlador Cultura y vista Index. El parámetro de cultura contiene el código de idioma, ejemplo:

                    @Html.ActionLink(" ", "Index", "Cultura", new { cultura = "es" }, new { @class = "navbar-link link-es" })

Por último para traducir el título de la página principal, sobre el ActionLink que apunta al Index de CulturaController. Introduciremos en el nombre el siguiente código con @Razor donde Resources.Cultura.Link, apunta a la traducción del título de la página:

            @Html.ActionLink(Resources.Cultura.Link, "Index", "Cultura", new { area = "" }, new { @class = "navbar-brand" })

Código:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>
    <link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />
    <script src="~/Scripts/modernizr-2.6.2.js"></script>
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink(Resources.Cultura.Link, "Index", "Cultura", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>
                        @Html.ActionLink(" ", "Index", "Cultura", new { cultura = "es" }, new { @class = "navbar-link link-es" })
                    </li>
                    <li>
                        @Html.ActionLink(" ", "Index", "Cultura", new { cultura = "ja" }, new { @class = "navbar-link link-jp" })
                    </li>
                    <li>
                        @Html.ActionLink(" ", "Index", "Cultura", new { cultura = "en" }, new { @class = "navbar-link link-us" })
                    </li>
                </ul>
            </div>
        </div>
    </div>

    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>© @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>

    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="~/Scripts/bootstrap.min.js"></script>
</body>
</html>

Resultados

resultado1
Navegación en castellano
resultado2
Navegación en japonés
resultado3
Navegación en inglés

En primer lugar, diseñaremos un formulario que enviara el modelo de Cliente, tanto las etiquetas como los placeholder descriptivos, serán traducidos accediendo a los recursos a través de código @Razor, siendo la sintaxis la siguiente:

@Resources.Cultura.Nombre

Sobre la referencia especificaríamos cada elemento del html que deseamos traducir, donde la aplicación cogería los valores del recurso Cultura, Cultura.en o Cultura.ja dentro de la carpeta de App_GlobalResources, dependiendo de la cultura seleccionada.

Para poder enviar el código de cultura en el Post del formulario y recibirlo en Index, sobre el botón de Submit.Seguidamente, establecemos como nombre el parámetro cultura y como valor el código actual de idioma de la aplicación gracias al método de CurrentUICulture:

    <button type="submit" name="cultura" value="@Thread.CurrentThread.CurrentUICulture.ToString()" class="btn btn-primary">@Resources.Cultura.Boton</button>

Por último, debajo de la cabecera, preguntamos si el modelo recibido es null y mostramos el mensaje de agradecimiento por ViewBag, y la fecha en la parte inferior:

@if (Model != null)
{
    <hgroup>
        <h3 style="color:green">@ViewBag.Agradecimiento</h3>
        <h4 style="color:green">@ViewBag.Donacion</h4>
    </hgroup>
}

Código:

@using System.Threading
@using Globalizacion.Models
@model Cliente
@{
    ViewBag.Title = "Index";
}

<h2>@Resources.Cultura.Home</h2>
<hr />
<div class="jumbotron">
    <h3><b>@Resources.Cultura.Pais</b></h3>
    <img src="~/Images/@Resources.Cultura.Bandera" style="height:150px;width:auto;border:2px solid black;border-radius:25px;" />
    <br />
    <p class="text-info">@Resources.Cultura.Idioma</p>
</div>

@if (Model != null)
{
    <hgroup>
        <h3 style="color:green">@ViewBag.Agradecimiento</h3>
        <h4 style="color:green">@ViewBag.Donacion</h4>
    </hgroup>
}

<form method="post">
    <div class="form-row">
        <fieldset>
            <legend>@Resources.Cultura.DatosPersonales</legend>
            <div class="form-group col-md-4">
                <label for="nombre">@Resources.Cultura.Nombre</label>
                <input type="text" class="form-control" name="nombre" placeholder="@Resources.Cultura.Nombre" required>
            </div>
            <div class="form-group col-md-4">
                <label for="apellido">@Resources.Cultura.Apellido</label>
                <input type="text" class="form-control" name="apellido" placeholder="@Resources.Cultura.Apellido" required>
            </div>
            <div class="form-group col-md-4">
                <label for="email">@Resources.Cultura.Email</label>
                <input type="email" class="form-control" name="email" placeholder="@Resources.Cultura.Email" required>
            </div>
        </fieldset>
    </div>
    <div class="form-row">
        <div class="col-md-6">
            <fieldset>
                <legend>@Resources.Cultura.Direccion</legend>
                <div class="form-group col-md-12">
                    <label for="inputAddress">@Resources.Cultura.Direccion</label>
                    <input type="text" class="form-control col-md-12" name="direccion" placeholder="@Resources.Cultura.Direccion" required>
                </div>
                <div class="form-group col-md-12">
                    <label for="codigopostal">@Resources.Cultura.CP</label>
                    <input type="number" class="form-control col-md-12" name="codigopostal" placeholder="@Resources.Cultura.CP" required>
                </div>
            </fieldset>
        </div>
        <div class="col-md-6">
            <div class="form-group col-md-12">
                <fieldset>
                    <legend>@Resources.Cultura.Contribucion</legend>
                    <div class="form-group col-md-12">
                        <label for="contribucion">@Resources.Cultura.Cantidad</label>
                        <input type="number" class="form-control col-md-12" name="contribucion" placeholder="@Resources.Cultura.Moneda" required>
                    </div>
                    <div class="form-group col-md-12">
                        <label for="comentario">@Resources.Cultura.Comentario</label>
                        <textarea placeholder="@Resources.Cultura.Comentario" name="comentario" class="form-control" rows="2"></textarea>
                    </div>
                </fieldset>
            </div>
        </div>
    </div>
    <button type="submit" name="cultura" value="@Thread.CurrentThread.CurrentUICulture.ToString()" class="btn btn-primary">@Resources.Cultura.Boton</button>
</form>
<hr />
<h3>@ViewBag.Fecha</h3>

Resultados de la aplicación

Como hemos visto en el código anterior, cada traducción hace referencia a Resources.Cultura, y se traducirá automáticamente.

Vista Index, seleccionando castellano, japonés e inglés

resultado4
Vista Index en castellano
resultado5
Vista Index en japonés
resultado6
Vista Index en inglés


Vista Index, mensaje de agradecimiento enviando el formulario en castellano, japonés e inglés

resultado7

Vista Index, mensaje al hacer (Post) en castellano
resultado9

Vista Index, mensaje al hacer (Post) en japonés
resultado8

Vista Index, mensaje al hacer (Post) en inglés

Como vemos en los resultados, tanto la moneda, como las referencias al mensaje de agradecimiento e imágenes son seleccionadas automáticamente dependiendo del código que envían por el parámetro de cultura los ActionLink al pulsar sobre cada país, ejemplo:

Apunte final

Tenemos que tener en cuenta a la hora de trabajar, si guardar las traducciones de las referencias en ViewBago llamando directamente sobre los elementos de la vistas con @Razor accediendo Resource, aunque ambas son correctas, al ampliarse la cantidad de vistas, sería recomendable guardar todos los valores en ViewBag, ya que los cambios en el controlador afectaría a todas las vista y los cambios serían mínimos, todo depende de cómo se quiera diseñar la aplicación.

Con esto tendríamos completo el proyecto de globalización, es un ejemplo fácil de implementar donde podemos ver distintos casos y usos de la globalización sobre nuestra aplicación.

Autor/a: Dragos Marian Alecu

Curso: Microsoft MCSA Web Applications + Microsoft MCSD App Builder + Xamarin

Centro: Tajamar

Año académico: 2018-2019

Código / recursos utilizados / Otros datos de interés:  https://github.com/Dalecu/Idiomas.git

Leave a Comment

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

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.