> For the complete documentation index, see [llms.txt](https://elguerre.gitbook.io/de0an/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://elguerre.gitbook.io/de0an/capitulo-04-la-construccion.-los-cimientos/nuevo-proyecto.md).

# Nuevo proyecto

A lo largo de esta sección crearemos nuestro primer proyecto UWP a partir de las plantillas nativas de Visual Studio. Añadiremos carpetas y nuevas clases para ir adecuándolo al patrón MVVM e incluso seguiremos algunas buenas prácticas tanto para nuestra aplicación como para otras que desarrollemos.

## Creando el proyecto

Utilizaremos cualquiera de las plantillas de la categoría “Visual C# - Windows Universal”. Sin embargo, antes de crear el proyecto, definamos la ruta física en la que situar nuestra solución y proyectos. Por ejemplo: “D:\dev\Taskin\\**main\src**”.

{% hint style="info" %}
**Nota**: Recordemos que la carpeta *main*, será la rama principal de nuestro proyecto en TFS. A partir de ella haremos los *Branching* y *Merging* tal y como vimos en el capítulo 1. Es posible que necesitemos otros recursos en nuestra carpeta *main*, así que crearemos una subcarpeta ***src*** en su interior, para tener claramente identificado el código fuente del resto de recursos.
{% endhint %}

Una vez identificada la ruta física de nuestro proyecto comenzaremos a componer la solución de nuestra aplicación:

1. Crear una solución indicando un nombre “\<Prefijo>.Taskin”. Donde \<Prefijo>, se corresponde con la parte fija del espacio de nombres (o *namespace*) que utilizaremos en todo el proyecto para identificar a las clases. Ej.: ElGuerre.Taskin.

   ![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-660aa01d127f8eb25b9ddb6f98d2794c664ed2f5%2Fimage24.png?alt=media)

**Figura 14.- Nueva solución para Task\[in]**

2. Mover la solución creada a la ruta física que buscamos. Como al generar una solución se genera una sub-carpeta (y no la queremos), moveremos ésta a nuestra ruta raíz y tendremos: “D:\dev\Taskin\main\src\\**ElGuerre.Taskin.sln**”.
3. Añadir a la solución un proyecto de tipo “Blank App (Universal Windows)” indicando nuestra ruta raíz.

   ![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-d632f0d94315c2f9e5c5049377eb8061c6c93eb8%2Fimage25.png?alt=media)

**Figura 15.- Creación de un nuevo proyecto Universal “Blank App”**

4. Seleccionar la versión mínima de la plataforma que soportará la aplicación.

   ![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-48e07838d0f352bf386f8ec869ae2833b39a3fa2%2Fimage26.png?alt=media)

**Figura 16.- Selección de la versión mínima al crear un nuevo proyecto UWP**

5. Hasta aquí, la ruta física y la estructura inicial de la solución queda como sigue:

   ![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-4cfe92f428d550cf071802d68b17c21c91ac2871%2Fimage27.png?alt=media)

**Figura 17.- Estructura inicial de la solución y ruta física para “Task\[in]”**

La solución se compone, por el momento de un único proyecto, formado por:

* Assets. Contenedor de imágenes, ficheros y otros recursos.
* App.xaml y App.xaml.cs. Ficheros principales de la aplicación donde se encuentra el punto de entrada o acceso (o *EntryPoint*) a la misma. Contiene la definición de recursos, diccionarios de la aplicación y eventos de inicio *OnLaunched*, activación *OnActivated*, suspensión *OnSuspending*, y, otros muchos, que son invocados cuando la aplicación es activada debido a la apertura o guardado de un fichero, al compartir información entre aplicaciones, etc. Para más detalle sobre estos eventos y el ciclo de vida de aplicaciones UWP visitar la página: <https://docs.microsoft.com/es-es/windows/uwp/launch-resume/app-lifecycle>.
* MainPage.xaml y MainPage.xaml.cs. Página inicial de la aplicación.
* Package.appxmanifest. Manifiesto de la aplicación.
* Project.json. Referencias de versiones y paquetes NuGet.

6. Compilar y ejecutar la aplicación para asegurar que todo es correcto.

![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-c1f5ac04fac7ccf765cba1439f4e8720a1d2d721%2Fimage28.png?alt=media)

**Figura 18.- Selección del dispositivo para ejecutar la aplicación**

A partir de aquí, añadiremos algunas carpetas y clases para comenzar a dar forma al patrón MVVM, y otras buenas prácticas.

7. Crear una nueva carpeta **ViewModels**, donde añadir las clases Vista-Modelo. Es decir, clases para el tratamiento de la lógica proporcionada por el modelo: propiedades, comandos, servicios, etc. y, la comunicación con la vista.
8. Crear dos clases (ViewModel) vacías: *MainViewModel.cs* y *AboutViewModel.cs*, que a su vez implementen las interfaces, *IMainViewModel.cs* y *IAboutViewModel.cs* respectivamente. Situaremos estas interfaces en una sub-carpeta *Interfaces*. ¡Repetiremos esto mismo para cada ViewModel que creemos!
9. Crear la clase ***ViewModelLocator*** que se corresponde con el contenedor de ID, cuyo objetivo es registrar los *ViewModels* y retornar sus instancias cuando sean solicitadas.

```csharp
public class ViewModelLocator
{
    private static IServiceLocator current;
    static ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
        current = ServiceLocator.Current;
        SimpleIoc.Default.Register<IMainViewModel, MainViewModel>();
        SimpleIoc.Default.Register<IAboutViewModel, AboutViewModel>();
    }
    public IMainViewModel Main { get { return current.GetInstance<IMainViewModel>(); } }
    public IAboutViewModel About { get { return current.GetInstance<IAboutViewModel>(); } }
}
```

10. Registrar en el fichero **App.xaml**, el contenedor de ID para acceder desde cualquier punto de la aplicación. Denotarlo con la clave (o *key*) ***Locator***.

```xml
<Application
    x:Class="ElGuerre.Taskin.Uwp.App"
    …
    xmlns:vm="using:ElGuerre.Taskin.Uwp.ViewModels">
    <Application.Resources>
        <ResourceDictionary>
            <vm:ViewModelLocator x:Key="Locator" />
        </ResourceDictionary>
    </Application.Resources>…
</Application>
```

11. Crear una nueva carpeta **Views**, donde incluir las páginas XAML.

![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-e02789d1d760d4fa5542b87ae9b4d26b56782917%2Fimage29.png?alt=media)

**Figura 19.- Añadir una nueva vista (página XAML)**

12. Mover la página *MainPage*, a la carpeta *Views* y actualizar los espacios de nombres (o *namespaces*), para que pasen a ser “ElGuerre.Taskin.Uwp.Views”. Asegurar que también realizamos el cambio en el código XAML.

![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-e05831aa04db5751102d0cdf424f82592bb601e0%2Fimage30.png?alt=media)

**Figura 20.- Cambio del espacio de nombres de la clase MainPage**

Las vistas definen los mecanismos de comunicación con la Vista-Modelo a través de *DataContext*, cuya fuente de datos es el contenedor de ID *Locator* y cuyo enlace a datos (o *binding)*, es la propia Vista-Modelo.

```xml
<Page x:Class="ElGuerre.Taskin.Uwp.Views.MainPage"
    . . .
    DataContext="{Binding Main, Mode=OneWay, Source={StaticResource Locator}}">
    . . .
</Page>
<Page x:Class="ElGuerre.Taskin.Uwp.Views.AboutPage"
    . . .
    DataContext="{Binding About, Mode=OneWay, Source={StaticResource Locator}}">
    . . .
</Page>
```

13. Crear una nueva carpeta **Services**, donde añadir clases de ayuda destinadas a aislar la lógica de acceso al dispositivo. Serán consumidas desde las clases *ViewModel*.
14. Crear una clase vacía *AppointmentService.cs* que implemente una nueva interfaz *IAppointmenteService.cs* situada en el interior de una nueva sub-carpeta *Interfaces*. ¡Las utilizaremos para el acceso a las citas (o *appointments*) del dispositivo!
15. Crear una nueva carpeta **Converters**, que como su propio nombre indica, incluirá clases conversores, que son invocadas por el motor de enlace a datos (o *binding*) para hacer la transformación de datos entre la Vista y el *ViewModel* y viceversa e implementan la interfaz *IValueConverter*. Un caso muy común es el conversor para la transformación entre un booleano y una propiedad *Visibility* de un control. Así, un valor booleano en el *ViewModel* se transforma en un valor *Visibility.Visible* o *Visibility.Collapsed* en la vista.

```csharp
public sealed class BooleanToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return (value is bool && (bool)value) ? Visibility.Visible : Visibility.Collapsed;
    }
    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return value is Visibility && (Visibility)value == Visibility.Visible;
    }
}
```

16. Preparar la aplicación para soporte a múltiples lenguajes o idiomas:
    1. Crear una carpeta **Strings**, donde incluir ficheros de recursos (.resw) por idioma o bien, una sub-carpeta por cada uno de ellos.
    2. Crear dos sub-carpetas *es* y *en-US*, para los idiomas español e inglés americano, respectivamente. Añadir en cada una de éstas un nuevo fichero de recursos *Resources.resw*, con las siguientes entradas.

       ![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-e8d259e28d441181cfaa8bdda6ee61e8713ff117%2Fimage31.png?alt=media)

**Figura 21.- Creando ficheros de recursos para múltiples lenguajes**

3. Añadir a la ruta raíz del proyecto una clase vacía *LocalizedStrings.cs.*
4. Registrar esta clase como nuevo recurso incluyéndolo en el fichero *App.xaml* al igual que para la clase *ViewModelLocator*.

```xml
<local:LocalizedStrings x:Key="LocalizedStrings" />
```

17. Por último, compilar y ejecutar la aplicación para asegurar que todo sigue siendo correcto.

De la misma manera que hemos ejecutado la aplicación en Windows, podemos hacerlo en un Tableta simulada (*Simulator*), emuladores de teléfonos, o bien, en un teléfono físico. Sigamos los siguientes pasos para corroborar que todo está dispuesto:

1. Conectar el teléfono al PC a través de un cable USB.
2. Habilitar el dispositivo para desarrollo tal y como ya aprendimos en el capítulo 1.
3. Seleccionar la plataforma *ARM* y *Device*.

   ![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-7fcafdfd6047eaac2b95a6369ce6d3d2bb2e7d24%2Fimage32.png?alt=media)

**Figura 22.- Ejecución de la aplicación en un dispositivo móvil**

4. Ejecutar y a esperar a que se instale y despliegue la aplicación en el teléfono.

Podemos utilizar la opción del menú contextual y hacer directamente un *Deploy*, para desplegar/instalar la aplicación en el teléfono sin necesidad de ejecutarla.

{% hint style="info" %}
**Nota**: El uso del teléfono, va a hacernos mucho más ágil la fase de pruebas. Durante un viaje en transporte público, desde el sofá de casa, o mejor aún, y como ya dijimos, prestando el teléfono a nuestros amigos para que comiencen a actuar como probadores o “testeadores” (*testers*).
{% endhint %}

Llegado este momento, hemos creado una solución de Visual Studio a partir de una plantilla, hemos creado nuevas carpetas, y hemos añadido clases y ficheros. Finalmente, hemos alcanzado las buenas prácticas que buscábamos consiguiendo una estructura base para una aplicación más sólida y adecuada al patrón MVVM. La siguiente figura muestra el resumen del trabajo realizado hasta el momento.

![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-b8ed367b9d5dc668eb60f3d0288d6273f9cf6400%2Fimage33.png?alt=media)

**Figura 23.- Estructura del proyecto Task\[in] en el Solution Explorer con el patrón MVVM**

Tenemos una estructura base para nuestro proyecto y conocemos cómo funciona el emulador, atemos los últimos cabos antes de comenzar nuestra rutina de desarrollo.

## Múltiples lenguajes y localización

Como hemos podido comprobar, al hablar de **localización** nos referimos a múltiples lenguajes, múltiples idiomas, o incluso múltiples culturas. En cualquiera de los casos, nos referimos a la capacidad de nuestra aplicación para tratar información en más de un idioma.

En este sentido, las guías de estilo de Microsoft son recopilaciones de reglas que definen las convenciones de idioma y estilo para idiomas específicos. Podemos encontrar toda esta información y mucho más en el portal lingüístico de Microsoft, “Conectando idiomas, culturas y tecnología” al que podemos acceder visitando la página: <https://learn.microsoft.com/es-es/globalization/reference/microsoft-terminology>).

### Localización de recursos

El idioma de un dispositivo se encuentra configurado por el propio usuario, por lo que la aplicación es capaz de saber el lenguaje activo en cada momento y mostrarlo automáticamente siempre que la aplicación lo soporte. Si bien, para conseguir la realidad de este automatismo seguiremos algunas pautas.

En primer lugar, estableceremos la localización predeterminada de la aplicación. Lo haremos en el fichero de manifiesto, en la pestaña *Application*, concretamente en el campo *Default language*.

![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-b7b91e41cca4035ed44614100154dbf2508cafe3%2Fimage34.PNG?alt=media)

**Figura 24.- Lenguaje predeterminado de la aplicación**

Windows utilizará este lenguaje si no encuentra el correspondiente en la configuración del teléfono.

Dejaremos el valor *en-US* como valor predeterminado. Trataremos así de llegar a más usuarios. El inglés se ha convertido casi en un requisito imprescindible a día de hoy. Por supuesto, añadiremos un nuevo idioma, el español (es).

Al hablar de localización de recursos, pensamos casi implícitamente en cadenas de textos o literales. Sin embargo, también podemos hacer que las imágenes soporten múltiples lenguajes.

### Textos

Para localizar los textos o literales, utilizaremos los dos ficheros *Resources.resw* que hemos creado previamente. Tenemos dos, uno para el inglés y otro para el español. La figura 21, detalla la nomenclatura de estos ficheros en sus carpetas.

Aunque no es lo recomendable, también podrían generarse diferentes ficheros para cada lenguaje en un mismo directorio. En tal caso, la distinción entre ellos vendría dada por el sufijo correspondiente al lenguaje o cultura: en-US, es, etc. Por ejemplo: Resources.en-US.resw, Resources.es.resw.

Cada uno de estos ficheros *Resources.resw* está formado por pares **nombre y valor**, además de un comentario. Donde el nombre es el identificativo del literal a localizar y deberá ser siempre el mismo para cada fichero de recursos. El valor, se corresponde con el texto o literal a traducir y dependerá del idioma.

El uso de estas cadenas de texto o literales se realizará de las siguientes formas posibles:

1. Mediante la clase ***LocalizatedStrings.cs***, que utilizaremos para unificar todos los accesos localizados. Se trata de una clase estática que utiliza a su vez, la clase *ResourceLoader*, para acceder a los recursos de los ficheros “*.resw”*.

```csharp
using Windows.ApplicationModel.Resources;
namespace ElGuerre.Taskin.Uwp
{
    public class LocalizedStrings
    {
        private static ResourceLoader resourceLoader = null;
        static LocalizedStrings()
        {
            resourceLoader = ResourceLoader.GetForViewIndependentUse();
        }
        public static ResourceLoader Current => resourceLoader;
        public static ResourceLoader GetForCurrentView(string name)
        {
            return ResourceLoader.GetForViewIndependentUse(name);
        }
        public static string AboutLiteral => Current.GetString("AboutLiteral");
        public static string AppTitle => Current.GetString("AppTitle");
        public static string AppVersion => Current.GetString("AppVersion"); }
}
```

Desde las clases *ViewModels*, invocaremos, por ejemplo, a la propiedad *AppTitle*.

Desde el código XAML:

```xml
<TextBlock Text="**{Binding AppTitle, Source={StaticResource LocalizedStrings}}"** />
```

2. Directamente utilizando el identificador de los controles, es decir el atributo ***x:Uid***.
   1. Añadir un sufijo al nombre a localizar, es decir, si queremos localizar el atributo *Content* de un control *Button,* incluiremos el par nombre-valor en cada fichero de recursos, como sigue:

      ![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-3bfdbb2227fe4ce717bcafdbcd622c4a37bc262b%2Fimage35.png?alt=media)

**Figura 25.- Localización del valor “Content” de un control “Button”**

2. Añadir el control *Button* a la página *Main*, indicado como *Uid* el valor *ButtonClick.*

```xml
<Button x:Uid="ButtonClick" />
```

Hay que destacar que en tiempo de diseño no se tiene acceso a valores localizados, por lo que hay que indicar también de manera explícita un valor para la propiedad *Content*.

Ahora, nuestra página *Main*, tiene el siguiente aspecto:

![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-c148c429c2805da5ef89d3a0a2dfdb8043e9be65%2Fimage36.png?alt=media)

**Figura 26.- Página Main y aplicación en ejecución**

Para la localización de textos dentro del propio fichero de manifiesto, usaremos el prefijo “**ms-resource**:” seguido del nombre a localizar. En la figura 24, podemos observar este uso para los campos *Display name* y *Description*.

Añadiremos dos nuevos pares a nuestros ficheros de recursos: AppDisplayName y AppDescription. Si ahora, ejecutamos nuevamente la aplicación, veremos que el título de la ventana ha cambiado por el nombre ya localizado (*AppDisplayName*).

{% hint style="info" %}
**Nota**: Si existe un par nombre-valor en los ficheros de recursos que tienen valores iguales, bastará con que la incluyamos en el fichero de idioma predeterminado. Eso sí, ten en cuenta que si decidimos cambiar el idioma predeterminado tendremos que añadir estas entradas.
{% endhint %}

### Imágenes

La localización de imágenes, aunque, probablemente menos usada, se realiza siguiendo la misma nomenclatura que para la localización de textos.

1. Crear dos sub-carpetas (“es” y “en-US”) dentro de la carpeta *Assets*. Una para cada idioma.
2. Situar en cada una de ellas una imagen “sample.png”:

   ![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-b60346586dcbfa74169e54461ddf26602bd4bb46%2Fimage37.png?alt=media)

**Figura 27.- Imágenes de ejemplo para su acceso de manera localizada**

3. Modificar la página *Main*, sustituyendo el control *TextBox* que mostraba el título de la aplicación, por este nuevo control de tipo imagen (*Image*).

![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-90c43e21fc41df8eef5f4dffa7a6abbe638576fb%2Fimage38.png?alt=media)

**Figura 28.- Página Main y ejecución de la aplicación**

Las imágenes del fichero manifiesto de la aplicación, siguen la misma nomenclatura. Incluso el propio editor es capaz de reconocerla. En la siguiente figura podemos, esta capacidad.

![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-c3b99b56261f637c3356269ef38617a9316d9825%2Fimage39.png?alt=media)

**Figura 29.- Localización de Imágenes en el manifiesto de la aplicación**

Para más detalle sobre localización visitar la página: <https://msdn.microsoft.com/es-es/windows/uwp/globalizing/guidelines-and-checklist-for-globalizing-your-app>

## Aplicaciones multilingües

Existe otra alternativa para la localización de textos, que va a facilitarnos más aún la preparación de nuestra aplicación para distintos idiomas. Esta alternativa se apoya en el “Kit de Herramientas para aplicaciones Multilingües” o *Multilingual App Toolkit* (**MAT**). Para la integración en nuestro proyecto:

1. Descargar la herramienta en el mismo idioma que Visual Studio desde la página: <https://developer.microsoft.com/en-us/windows/develop/multilingual-app-toolkit>
2. Una vez instalada, abrir el proyecto y habilitar la opción multilingües: “Tools – Enable Multilingual App Toolkit”.
3. Utilizar el menú “Project – Add translation languages” para añadir un nuevo idioma, por ejemplo: africano (*Afrikaans \[af]*).

![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-e5f56d9223b0eab2c0499ff196dec84a266c2089%2Fimage40.png?alt=media)

**Figura 30.- Añadiendo nuevo lenguaje con MAT**

4. Automáticamente se crea un nuevo fichero “ElGuerre.Taskin.Uwp.xlf”, que podremos editar con la herramienta “Multilingual Editor Tool” para hacer las traducciones de cada literal. Podremos, incluso, realizar la traducción completa.
5. Se crea también el nuevo fichero de recursos “Resources.resw” dentro de una nueva sub-carpeta *af*, cuyo contenido es inicialmente el mismo que el del idioma predeterminado, es decir, el inglés.

   ![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-f21f6319a950f7517bc91b857c5253880d601055%2Fimage41.png?alt=media)

**Figura 31.- Edición de nuevo idioma africano usando Multilingual Editor**

6. Tras la traducción, podemos ver el resultado, en la cuadrícula.
7. Revisar los textos traducidos y actualizar sus estados (*New, Needs Review, Translated, Final*). Éstos permiten trabajar a varios intérpretes simultáneamente en la traducción.
8. Ejecutar la aplicación cambiando la cultura, corroborar que automáticamente los textos aparecen en africano.

Revisemos algunos aspectos sobre lo anterior antes de dar por finalizado:

1. Aunque en el ejemplo hemos utilizado la traducción automática, no está recomendada y se requiere de la interacción con interlocutores para una traducción más adecuada.
2. Los ficheros XLF, al ser reconocidos por multitud de herramientas, podemos enviarlos a los intérpretes para que nos lo devuelvan traducidos más apropiadamente.
3. Se recomienda que el idioma inglés sea nuestro lenguaje de partida. Es más fácil encontrar intérpretes para una traducción del inglés a cualquier otro idioma.

{% hint style="info" %}
**Nota**: Nuestra aplicación soportará dos idiomas, inglés y español. Recuerda añadir un nuevo requerimiento a nuestro *Product Backlog* con el título: “Se requiere que la aplicación soporte dos idiomas: inglés como predeterminado y español”.
{% endhint %}

## Trabajando en tiempo de diseño

Cuando hablamos de diseño, al mismo tiempo nos referirnos a Blend y a otras de las herramientas ya conocidas. Nos referimos también a: maquetas, imágenes, temas, colores, tamaños de letras, tipo, etc.

En el capítulo 3, ya hemos visto cómo nuestra aplicación va tomando forma, y cómo Visual Studio y Blend nos facilitan la labor en lo que al diseño se refiere. Igualmente, tenemos que conocer que la cantidad de información a presentar no es la misma en tiempo de diseño y en tiempo de ejecución. Por tanto, una buena práctica se caracteriza por presentar la información lo más semejante posible en ambos casos utilizando uno de los dos caminos siguientes:

1. **Ficheros estáticos&#x20;*****Json***. A través de la propiedad *DataContext* y *DesignData* como fuente de datos, indicando la ruta física en la que se encuentra el fichero con los datos. Para nuestra clase *AboutViewModel*:
   1. Crear una sub-carpeta *Design* dentro de *ViewModels*.
   2. Añadir un nuevo fichero *About.json*.
   3. Hacer referencia desde la página *AboutPage.xaml* a este fichero tal y como se muestra en el siguiente código.

```xml
<Page
    …
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    ...
    d:DataContext="{Binding Source={d:DesignData Source=/Design/About.json, Type=data:DesignDataSource}}"
    …
    mc:Ignorable="d">
```

2. **Clases&#x20;*****Mocks***. También llamados *fakes* o *dumies*, son clases que imitan el comportamiento de clases reales proporcionando información estática o de prueba, concretamente para probar servicios, vistas-modelos, páginas, etc. La ventaja es que podemos utilizarlas para la creación de pruebas unitarias. Crearemos un *Mock* para nuestra clase *AboutViewModel* con estos ajustes:
   1. Crear una sub-carpeta *Mocks* dentro de *ViewModels*.
   2. Añadir una nueva clase *AboutViewModelMock.cs* que implemente la interfaz *IAboutViewModel.cs.*
   3. Y para concluir, incluir el siguiente código en la clase *ViewModelLocator*.

```csharp
if (ViewModelBase.IsInDesignModeStatic)
{
    SimpleIoc.Default.Register<IAboutViewModel, AboutViewModelMock>();
    …
}
else
{
    SimpleIoc.Default.Register<IAboutViewModel, AboutViewModel>();
    …
}
```

Tras los ajustes, el aspecto de nuestra carpeta *ViewModels* será el siguiente:

![](https://240651724-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FfrvHBNivOTy0fVKROgzo%2Fuploads%2Fgit-blob-79357906d27987401a29403cf42d4c6b65de850c%2Fimage42.png?alt=media)

**Figura 32.- Añadiendo ficheros JSON y Mocks para visualización en tiempo de diseño**

El siguiente paso es implementar cada una de las propiedades públicas de la Página *AboutPage.xaml*, pero esto lo prorrogaremos hasta el siguiente capítulo, donde, además, lo pondremos en marcha.
