I. Introduction

.NET est en phase de devenir de plus en plus utilisé, partout dans le monde, par les développeurs et les entreprises. Cela implique que les développeurs doivent ajouter des fonctionnalités utilisables partout sur la surface du globe. Il est donc important que leurs applications soient multilangues, afin qu'elles puissent être comprises par un maximum de personnes. Et pour ce faire, il existe un mécanisme très intéressant et simple à mettre en œuvre : la localisation.

II. Définition

La localisation est la technique qui vous permet de créer des applications multilangues en quelques clics de souris.
En effet, grâce à Visual Studio, une grande partie du travail est simplifié, car l'éditeur fait beaucoup pour vous, et c'est ce que nous allons voir dans les parties suivantes.

III. Mise en œuvre

III-A. Création des fichiers de langue

La première chose que vous devez faire, dans Visual Studio, pour pouvoir rendre votre application multilangues, c'est d'indiquer que justement, vous voulez une application localisable ;)
Pour cela, sur les propriétés de votre Form, repérer la propriété « Localizable » et positionnez-là à « True » (Vrai). Vous devez donc avoir ceci :

Image non disponible

Ensuite, vous devez choisir les langues dans lesquelles votre application sera disponible. Une fois encore, Visual Studio vous facilite le travail. En effet, toujours dans les propriétés de votre Form, repérez la propriété « Language » et, au moyen de la comboBox, choisissez la liste des langues que vous souhaitez (par exemple Anglais et Français) :

Image non disponible
Image non disponible

A ce moment là, Visual Studio va lier à votre formulaire trois fichiers de ressources :

  • un fichier Form1.resx
  • un fichier Form1.en.resx
  • un fichier Form1.fr.resx

Vous avez donc un fichier de ressources par langue choisie, plus un fichier de ressources principal. Vous pouvez visualisez ces fichiers en cliquant, dans l'explorateur de solutions, sur le petit plus à coté du nom de votre Form :

Image non disponible

Si vous double-cliquez sur les fichiers ressources correspondants aux langues choisies (donc Form1.en.resx et Form1.fr.resx), Visual Studio vous affiche à l'écran, dans un sorte d'éditeur graphique, le contenu du fichier de ressources choisi, fichier qui n'est rien d'autre qu'un simple fichier XML. Comme vous pouvez le voir, le fichier comporte un champ « name » et un champ « value » : nous pouvons donc largement supposer que name sera pour le nom et value sera la valeur correspondante à ce nom.

Image non disponible

Une fois l'ensemble des fichiers de langue créé, voyons maintenant comment les utiliser dans notre application.

III-B. Prérequis

Une fois les fichiers de langue créés, vous avez plusieurs choses à faire avant de pouvoir utiliser votre application :

  • Définition d'un ResourceManager : c'est lui qui ira chercher, dans vos fichiers de langue, la valeur correspondante au texte que vous voulez afficher.
  • Définition de la liste des CultureInfo (langues) que vous souhaitez utiliser.
  • Définition de la culture (langue) par défaut de votre application, au moyen de CurrentUICulture.

III-B-1. Définition du ResourceManager

Le resourceManager est l'élément qui vous permet d'accéder aux ressources spécifiques d'une culture, lors de l'exécution. Pour faire simple, c'est lui qui fera la correspondance, entre ce que vous devez d'afficher, et ce qu'il y a dans les fichiers de langue (si c'est un peu embrouiller, ne vous inquiétez pas, cela se simplifiera par la suite, avec les exemples).
Le constructeur du ResourceManager est un peu particulier : sachez juste qu'il prend en paramètres une chaîne de caractères composé du nom du namespace, suivi d'un point puis du nom de la ressource principale (souvenez-vous, il s'agit du fichier .resx, lié à votre Form, mais qui ne porte pas le nom d'une langue choisie ;).
L'autre paramètre qui le compose est l'assembly principales des ressources.

Voici ce que cela donne par le code :

Déclaration d'un ResourceManager
Sélectionnez
private System.Resources.ResourceManager RM = null;

...

// LeResourceManager prend en paramètre : nom_du_namespace.nom_de_la_ressource_principale
RM = new System.Resources.ResourceManager("Localisation.Form1", System.Reflection.Assembly.GetExecutingAssembly());

Comme je vous l'avais dit, rien de bien compliqué.
Vous trouverez plus d'informations sur le ResourceManager à cette adresse : ResourceManager.
Voyons maintenant le deuxième point important à effectuer : la définition des CultureInfo.

III-B-2. Définition des CultureInfo

Les CultureInfo représentent les différentes langues que vous désirez utiliser. La classe CultureInfo contient des informations spécifiques à une culture, par exemple la langue, la sous-langue, le pays et/ou la région ou le calendrier associés à la culture, ainsi que les conventions applicables à cette dernière.

Les noms des cultures respectent la norme RFC 1766. Il y a donc un format spécial à utiliser pour déclarer les cultures : <languagecode2>-<country/regioncode2>, où <languagecode2> est un code de deux lettres minuscules dérivé de ISO 639-1 et <country/regioncode2> est un code de deux lettres majuscules dérivé de ISO 3166. Par exemple, Anglais U.S. est « en-US ». Une liste de ces cultures, ainsi que diverses informations sur la classe CultureInfo peut être retrouvée à cette adresse : ici.


Maintenant, voyons comment déclarer ces CultureInfos :

Déclaration des CultureInfo
Sélectionnez
using System.Globalization;
...

private CultureInfo EnglishCulture = new CultureInfo("en-US");
private CultureInfo FrenchCulture = new CultureInfo("fr-FR");

Comme vous pouvez le constater, la classe CultureInfo n'a rien d'exceptionnel : il faut juste prendre garde à bien respecter la casse des chaîne de caractères que l'on passe au constructeur de la classe.

III-B-3. Définition de la culture par défaut

Pour que votre application puisse fonctionner correctement, vous devez lui indiquer une culture par défaut : c'est cette culture qui sera chargée au démarrage de l'application. En effet, sans cela, le programme ne saura pas quelle langue utiliser au chargement de l'application : cela pourra impliquer, dans le meilleur des cas, l'absence de texte dans les controles de votre Form, le déclenchement d'une exception non gérée, dans le pire des cas.
Vous devez utiliser System.Threading.Thread.CurrentThread.CurrentUICulture pour indiquer cette culture par défaut. Il est conseillé, pour la raison énoncée juste avant, de modifier le code du constructeur de votre Form, pour y insérer le code suivant :

Définition de la culture par défaut
Sélectionnez
// Définition de la culture par défaut
System.Threading.Thread.CurrentThread.CurrentUICulture = FrenchCulture;

Inséré dans le code de notre application, cela donne :

Insertion dans notre code
Sélectionnez
public Form1()
{
	//
	// Requis pour la prise en charge du Concepteur Windows Forms
	//
	
	// Définition de la culture par défaut
	System.Threading.Thread.CurrentThread.CurrentUICulture = FrenchCulture;

	InitializeComponent();

	//
	// TODO : ajoutez le code du constructeur après l'appel à InitializeComponent
	//
}

De cette façon, nous nous assurons bien que l'application aura FrenchCulture par défaut, autrement dit la culture fr-FR qui correspond au Français-France.

III-C. Utilisation des fichiers de langue

Maintenant que tous les prérequis sont remplis, vous pouvez continuer le développement de votre application : il vous faut accéder aux ressources contenues dans les fichiers de ressources. Pour cela, l'objet ResourceManager possède la méthode  GetString, qui vous permet de récupérer la valeur de la ressource spécifiée pour la culture courante. Plus simplement, cela vous permet de récupérer la valeur de la ressource passée en paramètre pour l'affecter à la propriété Text du contrôle de votre Form.
Voyons ce que cela veut dire par le code :

Utilisation de la méthode RM.GetString
Sélectionnez
using System.Globalization;
...

private void Form1_Load(object sender, System.EventArgs e)
{
	// LeResourceManager prend en paramètre : nom_du_namespace.nom_de_la_ressource_principale
	RM = new System.Resources.ResourceManager("Localisation.Form1", typeof(Form1).Assembly);

	// Affecte la valeur de la ressource MainTitle à la proriété Text de la fenêtre principale
	this.Text = RM.GetString("MainTitle");
};

Avec les explications que je vous ai fourni précédemment, vous devriez pouvoir comprendre ce bout de code facilement :) On affecte la valeur de la ressource MainTitle à la propriété Text de la fenêtre principale.
Mais, pour que tout cela fonctionne parfaitement, il faut justement définir la valeur de la ressource MainTitle, et cela dans tous vos fichiers de ressources. Pour cela, ouvrez les fichiers de ressources que Visuail Studio a créés pour vous au début (Form1.en.resx et Form1.fr.resx) puis :

  1. Dans la colonne « name », indiquez le nom de la ressource à utiliser (dans notre cas, il s'agit de MainTitle)
  2. Dans la colonne « value », indiquez la valeur de cette ressource (par exemple « Bonjour le monde »)

N'oubliez pas : Vous devez effectuer ces deux (simples) opérations pour tous les ficihers de ressources que vous avez, tout en gardant à l'esprit que vous devrez traduire, dans la langue désirée, la valeur des ressources que vous inscrivez.
Voici par exemple, le résultat pour notre application de test :

Fichier de ressource français :

Image non disponible


Fichier de ressource anglais :

Image non disponible


Il ne vous reste plus qu'a compiler puis exécuter votre application pour observer le résultat :

Image non disponible

Pour être sur que la localisation fonctionne bien et que l'application peut aussi s'exécuter en anglais, il nous suffit de remplacer cette ligne :

Vérification
Sélectionnez
System.Threading.Thread.CurrentThread.CurrentUICulture = FrenchCulture;

par cette ligne :

Vérification
Sélectionnez
System.Threading.Thread.CurrentThread.CurrentUICulture = EnglishCulture;

Puis de relancer l'application et d'observer que le titre de la fenêtre principale a bien changé :

Image non disponible

Voila, vous venez de réaliser une application multilangue :) Mais il serait peut-être intéressant de pouvoir changer la langue en cours d'application, comme le font la plupart de IHM (Interface Homme-Machine). C'est ce que nous allons voir tout de suite.

Lorsque vous réaliser une application localisable, à la compilation, des répertoires pour tous les langues choisies sont créés avec, à l'intérieur, des fichiers du type « Nom_du_namespace.resources.dll ». Ces fichiers sont en fait les fichiers de ressources de votre application, compilés en DLL.

Image non disponible

III-D. Changer la langue courante de l'application

Pour pouvoir changer de langue au cours de votre application, vous devez juste changer la culture en cours au moyen de System.Threading.Thread.CurrentThread.CurrentUICulture (qui nous a permis, je vous le rappelle, de définir la culture par défaut de votre application).
Voici le code de notre application, dans le cas où nous avons deux boutons-radios, un pour chaque langue (notez que cela fonctionne également avec des CheckBox, des MenusItems, etc….):

Changement de la langue au cours de l'application
Sélectionnez
private void radioButton2_CheckedChanged(object sender, System.EventArgs e)
{
	if ( radioButton1.Checked )
	{
		System.Threading.Thread.CurrentThread.CurrentUICulture = FrenchCulture;
	}
	else
	{
		System.Threading.Thread.CurrentThread.CurrentUICulture = EnglishCulture;
	}
	
	this.Text = RM.GetString("MainTitle");
}

Ce code, bien que fonctionnel, ne s'avère pas forcément très pratique : en effet, dans notre exemple, nous n'affichons qu'une seule ressource. Mais vos applications comportent bien plus d'un seul contrôle. Par conséquent, vous serez amené à écrire des parties de code en double, voire plus : celles qui se chargent de l'affichage. Pour résoudre ce problème, je vous suggère de créer une méthode AfficherTexte, dans laquelle vous mettrez votre code. Ensuite, il ne vous restera plus qu'à appeler cette méthode à chaque fois que vous en avez besoin. Cela vous fera gagner beaucoup de temps pour vos développements.
Voici une mise en application, sur notre application de test, de cette technique :

Méthode AfficherTexte
Sélectionnez
/// <summary>
/// Méthode chargée de l'affichage du texte des contrôles à partir des ressources des fichiers de langue.
/// </summary>

private void AfficherTexte()
{
	this.Text = RM.GetString("MainTitle");
}

Et voici maintenant l'appel à cette méthode :

Utilisation de la méthode AfficherTexte
Sélectionnez
private void radioButton2_CheckedChanged(object sender, System.EventArgs e)
{
	if ( radioButton1.Checked )
	{
		System.Threading.Thread.CurrentThread.CurrentUICulture = FrenchCulture;
	}
	else
	{
		System.Threading.Thread.CurrentThread.CurrentUICulture = EnglishCulture;
	}
			
	//this.Text = RM.GetString("MainTitle");
	AfficherTexte();
}

En compilant et exécutant notre application, nous nous apercevons bien, lors du changement de bouton, que le titre de la fenêtre principale change lui aussi de manière automatique:

Application en français :

Image non disponible

Application en anglais :

Image non disponible

IV. Prévention contre les ressources non-disponibles

Les fichiers de ressources étant compilés en DLL pour être utilisés par l'application, rien n'empêche un utilisateur de supprimer le répertoire contenant la DLL en question : à ce moment-là, une exception surgira. Pour éviter ce problème, vous pouvez utiliser la méthode GetResourceSet pour vérifier qu'une ressource est bien disponible et, si cela n'était pas le cas, désactiver l'item permettant sa sélection.
La méthode GetResourceSet, qui retourne un ResourceSet ou null, prend 3 paramètres :

  • La CultureInfo à rechercher
  • Un booléen qui, s'il est positionné à true(vrai) permet de charger le ResourceSet
  • Un autre booléen qui indique s'il faut ou non essayez d'utiliser les objets CultureInfo parents pour vérifier s'ils existent, dans le cas où le ResourceSet ne peut pas être chargé
 

Concrètement, cette méthode vous permet de tester si une ressource est bien disponible dans le répertoire de votre application. Cela peut s'avérer très pratique si vous souhaitez désactiver l'item d'un menu (ou autre) parce que la ressource n'est plus disponible.
Voici le code à utiliser avec GetResourceSet :

Utilisation de GetResourceSet
Sélectionnez
if ( RM.GetResourceSet(FrenchCulture, true, false) == null )
{
	this.radioButton1.Enabled = false;
}
if ( RM.GetResourceSet(SpanishCulture, true, false) == null )
{
	this.radioButton2.Enabled = false;
}

V. Conclusion

Grâce à cet article, vous avez pu apprendre comment créer, simplement et rapidement (hormis pour les traductions ;) une application localisable, c'est-à-dire multilangues.

VI. Téléchargement

Télécharger les sources de l'application de test : Sources C# pour Visual Studio et Sources VB.NET pour Visual Studio.