Interface multilingues avec WPF

INTERFACE MULTILINGUES POUR APPLICATIONS WPF

Préambule

Ce tutoriel va présenter d'une manière simple comment réaliser une interface multilingues pour vos applications WPF.
Tutoriel utilisant VS2010

Introduction

Aujourd'hui, nombre d'applications sont multilingues. Il faut donc, lorsque nous créons nos propres applications, prévoir nos interfaces utilisateurs comme étant multilingues. Ce tutorial va montrer une manière de créer des interfaces multilingues aisément. Il existe, à n'en pas douter, de bien meilleures façons de créer des interfaces multilingues, mais celle-ci a le mérite d'être extrêmement simple.

Comment créer une interface multilingues

Création du projet

Nous allons commencer par créer un nouveau projet. Nommons-le MultilingualUI.

Une fois notre projet créé, nous allons lui ajouter un nouveau projet de type Bibliothèque de classes.

Nous allons le nommer MultilingualUI.Resources. Bien sûr, nous ajoutons ce projet à la solution actuelle.

Nous obtenons ceci dans notre solution :

Nous allons maintenant créer les ressources nécessaires pour pouvoir créer une interface multilingues.

Création des ressources nécessaires

Ici, nous allons créer de simples fichiers *.resx, comme nous le ferions si nous utilisions la technologie Winforms. Ici la langue par défaut sera l'anglais, puis nous ajouterons un fichier pour avoir une interface en anglais.

En premier lieu, cliquez-droit sur MultilingualUI.Resources et dans le menu contextuel qui apparait, sélectionnez Ajouter, puis Nouvel élément

Dans la boite de dialogue qui apparaît, sélectionnez Général dans l'arbre à vue, puis sélectionner Fichier de ressources dans la listbox, et nommez votre fichier Languages.resx

Notre solution se met à jour comme ceci :

Refaites la même étape au-dessus, mais prenez garde à nommer le nouveau fichier ressources comme ceci : Languages.fr.resx.

Une fois cela fait, la solution est comme ceci :

Comme nous pouvons le constater, il n'y a qu'un seul fichier Designer. Oh joie, cela va nous simplifier le travail.

Double cliquez sur Languages.resx pour faire apparaître l'éditeur de ressources et remplissez-le comme ceci :

Maintenant, double cliquez sur Languages.fr.resx pour faire apparaître l'éditeur de ressources et remplissez-le comme cela :

Maintenant, notre dernière phase pour que tout cela soit parfait. Il faudra exposer nos valeurs si nous voulons pouvoir les utiliser. Effectivement, lorsque nous créons un fichier de ressources, le designer met les membres en internal. On ne va pas y toucher, si le designer a mis les membres en internal, il doit y avoir une raison.

Renommez le fichier Class1.cs en LanguageHelper.cs.

Supprimons les directives, cela ne nous servira à rien.

Notre fichier se présente comme suit :

namespace MultilingualUI.Resources
{
    public class LanguageHelper
    {
    }
}

Nous allons qualifier tous nos membres en static. La classe aussi le sera. Et nous allons instancier notre classe statique avec la culture par défaut. Cela donne :

namespace MultilingualUI.Resources
{
     static public class LanguageHelper
    {
        static LanguageHelper()
        {
             Languages.Culture = System.Globalization.CultureInfo.CurrentCulture;
        }
    }
}

Et voilà, nous avons déjà une culture par défaut qui est celle de l'OS.

Maintenant nous allons exposer toutes nos string. Au final, nous avons :

namespace MultilingualUI.Resources
{
    static public class LanguageHelper
    {
        static LanguageHelper()
        {
            Languages.Culture = System.Globalization.CultureInfo.CurrentCulture;
        }

        static public string MenuItemHeaderFile
        {
            get { return Languages.MenuItemHeaderFile; }
        }

        static public string MenuItemHeaderFileDescription
        {
            get { return Languages.MenuItemHeaderFileDescription; }
        }

        static public string Ready 
        {
            get { return Languages.Ready; }
        }

        static public string MenuItemHeaderFileNewProject
        {
            get { return Languages.MenuItemHeaderFileNewProject; }
        }

        static public string MenuItemHeaderFileNewProjectDescription
        {
            get { return Languages.MenuItemHeaderFileNewProjectDescription; }
        }

        static public string MenuItemHeaderFileOpenProject
        {
            get { return Languages.MenuItemHeaderFileOpenProject; }
        }

        static public string MenuItemHeaderFileOpenProjectDescription
        {
            get { return Languages.MenuItemHeaderFileOpenProjectDescription; }
        }

        static public string MenuItemHeaderFileSaveProject
        {
            get { return Languages.MenuItemHeaderFileSaveProject; }
        }

        static public string MenuItemHeaderFileSaveProjectDescription
        {
            get { return Languages.MenuItemHeaderFileSaveProjectDescription; }
        }

        static public string MenuItemHeaderFileExitApp
        {
            get { return Languages.MenuItemHeaderFileExitApp; }
        }

        static public string MenuItemHeaderFileExitAppDescription
        {
            get { return Languages.MenuItemHeaderFileExitAppDescription; }
        }
    }
}

Vous pouvez à présent construire le projet. Attention cependant à bien vérifié dans les propriétés de chaque fichier resx que l'action de génération est mise à Resource Incorporée.

Référencement des ressources

Maintenant, nous allons référencer notre DLL dans notre projet. Pour cela, dans le projet MultilingualUI, cliquez-droit sur References, et cliquez sur Ajouter une référence.

Dans la boite de dialogue qui s'affiche, allez dans l'onglet Projets et ajouter la référence à MultilingualUI.Resources.

Création d'un exemple

Avant de voir comment utiliser nos ressources de langues, il convient de créer une petite UI.

Collez ceci dans MainWindow.xaml

<DockPanel LastChildFill="False" Name="dock">
    <Menu DockPanel.Dock="Top" Name="menu">
        <MenuItem Header="" Tag="" MouseEnter="MenuItem_MouseEnter" MouseLeave="MenuItem_MouseLeave">
            <MenuItem Header="" Tag="" MouseEnter="MenuItem_MouseEnter" MouseLeave="MenuItem_MouseLeave" />
            <MenuItem Header="" Tag="" MouseEnter="MenuItem_MouseEnter" MouseLeave="MenuItem_MouseLeave" />
            <MenuItem Header="" Tag="" MouseEnter="MenuItem_MouseEnter" MouseLeave="MenuItem_MouseLeave" />
            <Separator />
            <MenuItem Header="" Tag="" MouseEnter="MenuItem_MouseEnter" MouseLeave="MenuItem_MouseLeave" />
        </MenuItem>
    </Menu>
    <StatusBar DockPanel.Dock="Bottom" FontSize="12">
        <StatusBarItem Content="" HorizontalAlignment="Left" Name="statusBarItemDescription" />
    </StatusBar>
</DockPanel>

Puis dans le fichier MainWindow.xaml.cs, ajouter les évènements MouseEnter et MouseLeave.

private void MenuItem_MouseEnter(object sender, MouseEventArgs e)
{
}

private void MenuItem_MouseLeave(object sender, MouseEventArgs e)
{
}

Maintenant, nous allons pouvoir (enfin) voir comment rendre notre interface multilingue.

Utilisation des ressources

Ici, nous allons à la fois jouer avec le code-behind et le code XAML. Notre dll est référencée, une partie du travail est donc faite. Maintenant, dans le code XAML, nous allons ajouter l'espace de noms (ainsi que l'assembly dans laquelle se trouve cet espace de noms). En XAML, cela se fait en passant par la `commande' xmlns. Donc au tout début du fichier (où se trouvent les déclarations xmlns), on va ajouter notre déclaration :

xmlns:language="clr-namespace:MultilingualUI.Resources;assembly=MultilingualUI.Resources"

Le menu sera comme suit :

Fichier
----------------------
Nouveau
Ouvrir
Enregistrer
Quitter

En prenant le 1er menu item, nous allons lui donner son header et son tag (le tag sera utilisé par la status bar pour afficher des informations concernant le menu mis en surbrillance).

Nous savons que nos données sont statiques. Pour pouvoir s'en servir nous aurons besoin du mot x :Static.

Pour le premier menu item, les 2 objets strings réservés se nomment :

MenuItemHeaderFile
MenuItemHeaderFileDescription

Ce qui donne pour le menu Fichier, ceci :

<MenuItem Header="{x:Static language:LanguageHelper.MenuItemHeaderFile}" Tag="{x:Static language:LanguageHelper.MenuItemHeaderFileDescription}" MouseEnter="MenuItem_MouseEnter" MouseLeave="MenuItem_MouseLeave">

< !-- ... -->

</MenuItem>

En suivant le principe, répétez la même technique pour le reste des menus :

<DockPanel LastChildFill="False" Name="dock">
    <Menu DockPanel.Dock="Top" Name="menu">
        <MenuItem Header="{x:Static language:LanguageHelper.MenuItemHeaderFile}" Tag="{x:Static language:LanguageHelper.MenuItemHeaderFileDescription}" MouseEnter="MenuItem_MouseEnter" MouseLeave="MenuItem_MouseLeave">
            <MenuItem Header="{x:Static language:LanguageHelper.MenuItemHeaderFileNewProject}" Tag="{x:Static language:LanguageHelper.MenuItemHeaderFileNewProjectDescription}" MouseEnter="MenuItem_MouseEnter" MouseLeave="MenuItem_MouseLeave" />
            <MenuItem Header="{x:Static language:LanguageHelper.MenuItemHeaderFileOpenProject}" Tag="{x:Static language:LanguageHelper.MenuItemHeaderFileOpenProjectDescription}" MouseEnter="MenuItem_MouseEnter" MouseLeave="MenuItem_MouseLeave" />
            <MenuItem Header="{x:Static language:LanguageHelper.MenuItemHeaderFileSaveProject}" Tag="{x:Static language:LanguageHelper.MenuItemHeaderFileSaveProjectDescription}" MouseEnter="MenuItem_MouseEnter" MouseLeave="MenuItem_MouseLeave" />

            <Separator />

            <MenuItem Header="{x:Static language:LanguageHelper.MenuItemHeaderFileExitApp}" Tag="{x:Static language:LanguageHelper.MenuItemHeaderFileExitAppDescription}" MouseEnter="MenuItem_MouseEnter" MouseLeave="MenuItem_MouseLeave" />
        </MenuItem>
    </Menu>

    <StatusBar DockPanel.Dock="Bottom" FontSize="12">
    <StatusBarItem Content="{x:Static language:LanguageHelper.Ready}" HorizontalAlignment="Left" Name="statusBarItemDescription" />
    </StatusBar>
</DockPanel>

La toute dernière chose à faire maintenant est de détecter lorsque l'on est ou non sur un menu item, et d'afficher la bonne info. Donc dans l'évènement qui gère l'entrée de la souris sur un item, on ajoute ceci :

statusBarItemDescription.Content = (string)((MenuItem)e.Source).Tag;

Cela nous permet de mettre à jour la status bar avec la bonne info.

Enfin lorsque dans l'évènement Leave on ajoute ceci :

statusBarItemDescription.Content = LanguageHelper.Ready;

Maintenant, pressez F5 et admirez le résultat, votre interface est en français. Si vous n'êtes pas convaincus par l'exemple, changez Languages.fr.resx par Languages.da.resx et relancez l'application, et boum, l'interface est en anglais.

Conclusion

Avec ce tutoriel, vous avez appris comment créer une interface multilingue. Il existe certes d'autres façons de gérer la chose mais celle-ci est relativement simple

A voir également
Ce document intitulé « Interface multilingues avec WPF » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous