Il y a quelques mois, j’avais mis en ligne une façon de traduire ses applications en plusieurs langues, grâce à LocBaml. Nous allons voir maintenant comment traduire une application WPF mais sans cet outil.
La mise en place est très simple et il a l’avantage, par rapport à LocBaml, qu’on puisse traduire l’application « à la volée » sans relancer celle-ci. Par contre, il faut être plus rigoureux : là où LocBaml nous génère les clefs (x:Uid) des contenus de nos différents contrôles, ici il faut bien prendre soin de le faire soi-même.
Nous allons créer un dictionnaire de ressource pour la langue français et un autre pour la langue anglaise :
Pour plus de commodité, nous allons nommer les dictionnaires de ressources avec le code pays :
Dans ces fichiers, j’ajoute quelques balises afin de contenir les phrases dans la langue adéquate :
<!-- Fichier en-US.xaml -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="Culture">en-US</system:String>
<system:String x:Key="Window">Window</system:String>
<system:String x:Key="cmdExit">Exit</system:String>
<system:String x:Key="lblWelcome">Hello</system:String>
<system:String x:Key="World">World !</system:String>
<system:String x:Key="lblChangeLangage">Change language</system:String>
</ResourceDictionary>
<!-- Fichier fr-FR.xaml -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="Culture">fr-FR</system:String>
<system:String x:Key="Window">Fenêtre</system:String>
<system:String x:Key="cmdExit">Quitter</system:String>
<system:String x:Key="lblWelcome">Bonjour</system:String>
<system:String x:Key="World">Tout le monde !</system:String>
<system:String x:Key="lblChangeLangage">Changer de langue</system:String>
</ResourceDictionary>
Puis on va indiquer le ResourceDirectionary de la langue par défaut dans le point d’entrée de notre application (App.xaml), c’est cette ressource qui sera chargée au démarrage de l’application (bien sûr, ici ce n’est que pour exemple, il y aurait moyen de faire mieux dans le contexte où l’on retient le choix de la langue de l’utilisateur, qui peut être différent que le français :)) :
<Application x:Class="MultilangueSansLocBaml.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources\fr-FR.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Maintenant je vais ajouté une méthode qui permettra de changer la ressource de langue utilisée dans l’application :
Ici, nous allons chercher la ressource chargée, puis la supprimer afin d’ajouter la nouvelle ressource, puis changer la culture en cours. En effet, nous avons mis dans le XAML une ressource (fr-FR.xaml) chargée par défaut, il faut donc s’en “débarrassé” afin de mettre une autre ressource.
Pour savoir quelle est la ressource chargée, on va au démarrage de l’application récupérer le ResourceDictionary :
public void ChangeLangage(Uri dictionnaryUri)
{
if (String.IsNullOrEmpty(dictionnaryUri.OriginalString) == false)
{
ResourceDictionary objNewLanguageDictionary =
(ResourceDictionary)(LoadComponent(dictionnaryUri));
if (objNewLanguageDictionary != null)
{
this.Resources.MergedDictionaries.Remove(obj);
this.Resources.MergedDictionaries.Add(objNewLanguageDictionary);
CultureInfo culture =
new CultureInfo((string)Application.Current.Resources["Culture"]);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
}
}
Maintenant passons à l’interface de notre application, pour exemple, nous allons utiliser cette fenêtre :
Au clique sur “Changer de langue”, l’interface se mettra automatiquement à jour avec la ressource anglaise.
private ResourceDictionary obj;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
foreach (ResourceDictionary item in this.Resources.MergedDictionaries)
{
if (item.Source != null && item.Source.OriginalString.Contains(@"Resources\"))
{
obj = item;
}
}
}
Et le code pour changer la langue quand on clique sur le bouton :
<Window x:Class="MultilangueSansLocBaml.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{DynamicResource Window}" Height="138" Width="203">
<Grid>
<StackPanel>
<Button Content="{DynamicResource lblWelcome}" Click="Button_Click_1" />
<Button Content="{DynamicResource lblChangeLangage}" Click="Button_Click" />
</StackPanel>
</Grid>
</Window>
Et pour charger un élément d’une ressource en C# :
private void Button_Click_1(object sender, RoutedEventArgs e)
{
MessageBox.Show((string) Application.Current.Resources["World"]);
}
Bien sûr, ceci n’est qu’une ébauche. On peut faire quelque chose de beaucoup plus complet, mais l’essentiel est là :).
Les sources du projet peuvent être téléchargés ici.
A bientôt !