Problema:
Queremos tener una aplicación multiidioma. Necesitamos poder crear y mantener fácilmente los textos
de cada idioma sin tener conocimientos técnicos.
Selección de idioma desde el CodeBehind o desde la ventana (MenuItem, ComboBox, etc...)
Formulario
En el formulario asignamos las propiedade de texto susceptibles de variar según el idioma de la
siguiente forma (por ejemplo):
Content="{Binding Textos[Ayuda]}"
y de forma genérica:
Propiedad = "{Binding DiccionarioClaveValor [Clave] }"
Del mismo modo que textos, es interesante este método pues NOS PERMITE MODIFICAR CUALQUIER TIPO
DE PROPIEDAD ASOCIADA A UN PARÁMETRO COMO EL IDIOMA, (por ejemplo, la imagen de una bandera).
<Window x:Class="MultiIdioma.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Binding Textos[Titulo]}" Height="350" Width="525">
<StackPanel>
<Label Content="{Binding Textos[Ayuda]}" />
<ComboBox SelectedValue="{Binding IdiomaActual}"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding ListaIdiomas}" />
<
Button Content
="{Binding Textos[Boton]}"/>
</StackPanel>
</Window>
CodeBehing
En el siguiente código se muestra cómo se exponen las propiedades Text (Dictionary con los textos cargados desde XML),
ListaIdiomas (contenido del ComboBox para la selección del idioma) e IdiomaActual, asignado desde la ventana para
actualizar el contenido del Dictionary.
El código está suficientemente comentado para seguir en detalle qué realiza.
using System.Collections.Generic;
using System.Xml;
using System.ComponentModel;
namespace MultiIdioma
{
/*
* Implementamos el comportamiento de la
Interfaz INotifyPropertyChanged.
* Esto permitirá al View (Window)
interceptar cualquier cambio en los
* datos
*/
public class VM : INotifyPropertyChanged
{
// Constructor principal que asigna un idioma inicial
para
// la aplicación
public VM()
{ IdiomaActual = "castellano"; }
/*
* Utilizada cuando cambiamos el contenido del
Diccionario Textos
*/
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{ PropertyChanged(
this,
new PropertyChangedEventArgs(info));
}
}
/*
* Idiomas disponibles. Se muestran en el combo de
selección de idioma
*/
public List<string> ListaIdiomas
{
get
{
return new List<string>() {
"catala",
"castellano" };
}
}
//Diccionario de textos accesible en la View (Window)
Dictionary<string, string> textos;
public Dictionary<string, string> Textos
{
get { return textos; }
set
{
textos = value;
NotifyPropertyChanged("Textos");
}
}
/*
* Propiedad cuyo valor se asigna desde la Ventana
(Binding desde el
* combo de selección de idioma). Al cambiar el idioma,
se ejecuta la función
* que actualiza los textos.
*/
private string idiomaActual;
public string IdiomaActual {
get { return idiomaActual; }
set
{
idiomaActual = (string)value;
SetIdioma(idiomaActual);
}
}
//Carga del diccionario de idioma a partir de un XML
public void SetIdioma(string idioma)
{
XmlDocument doc = new XmlDocument();
doc.Load(@"ruta\Textos.xml");
XmlNodeList nodos = doc.GetElementsByTagName(idioma);
Dictionary<string, string> textos =
new Dictionary<string, string>();
foreach (XmlNode nodo in nodos)
{
textos.Add(
nodo.Attributes["key"].Value,
nodo.Attributes["text"].Value
);
}
Textos = textos;
}
}
}
XML con la información de idioma.
<?xml version="1.0" encoding="utf-8" ?>
<textos>
<catala key="Titulo" text="Finestra multiidioma" />
<catala key="Boton" text="Un botó" />
<catala key="Ayuda" text="Siusplau, seleccioni un idioma al Combo" />
<castellano key="Titulo" text="Ventana multiidioma" />
<castellano key="Boton" text="Un botón" />
<castellano key="Ayuda" text="Por favor, selecciona un idioma en el ComboBox" />
</textos>