Pour afficher l’article en anglais, activez la case d’option Anglais. Vous pouvez aussi afficher la version anglaise dans une fenêtre contextuelle en faisant glisser le pointeur de la souris sur le texte.
Traduction
Anglais

Récupération de ressources dans des applications de bureau

 

Date de publication : novembre 2016

Quand vous utilisez des ressources localisées dans des applications de bureau du .NET Framework, vous devez, dans l’idéal, empaqueter les ressources pour la culture neutre ou par défaut avec l’assembly principal et créer un assembly satellite séparé pour chaque langue ou culture prise en charge par votre application. Vous pouvez ensuite utiliser la classe ResourceManager pour accéder aux ressources nommées, comme indiqué dans la section suivante. Si vous choisissez de ne pas incorporer les ressources dans l’assembly principal et les assemblys satellites, vous pouvez également accéder directement aux fichiers .resources binaires, comme cela est expliqué dans la section Récupération de ressources de fichiers .resources, plus loin dans cet article. Pour récupérer des ressources dans des applications du Windows 8.x Store, consultez Création et récupération de ressources dans les applications du Windows Store dans le Centre de développement Windows.

La classe ResourceManager fournit l’accès aux ressources au moment de l’exécution. Utilisez la méthode ResourceManager.GetString pour récupérer des ressources de type chaîne et la méthode ResourceManager.GetObject ou ResourceManager.GetStream pour récupérer des ressources d’un autre type. Chaque méthode a deux surcharges :

  • Une surcharge dont le paramètre unique est une chaîne qui contient le nom de la ressource. La méthode tente de récupérer cette ressource pour la culture du thread actuel. Pour plus d’informations, consultez les méthodes GetString(String), GetObject(String) et GetStream(String).

  • Une surcharge qui a deux paramètres : une chaîne contenant le nom de la ressource, et un objet CultureInfo représentant la culture pour laquelle la ressource doit être récupérée. Si une ressource définie pour cette culture est introuvable, le Gestionnaire des ressources utilise des règles de secours pour récupérer une ressource appropriée. Pour plus d’informations, consultez les méthodes GetString(String, CultureInfo), GetObject(String, CultureInfo) et GetStream(String, CultureInfo).

Le Gestionnaire des ressources utilise le processus de secours pour les ressources pour déterminer de quelle manière l’application récupère les ressources spécifiques de la culture. Pour plus d’informations, consultez la section « Processus de secours pour les ressources » dans Empaquetage et déploiement de ressources dans des applications de bureau. Pour plus d’informations sur l’instanciation d’un objet ResourceManager, consultez la section « Instanciation d’un objet ResourceManager » dans la rubrique de la classe ResourceManager.

L’exemple suivant appelle la méthode GetString(String) pour récupérer les ressources de type chaîne de la culture d’interface utilisateur actuelle. Il inclut une ressource de chaîne neutre pour la culture Anglais (États-Unis), et les ressources localisées pour les cultures Français (France) et Russe (Russie). La ressource Anglais (États-Unis) suivante se trouve dans un fichier nommé Strings.txt :

TimeHeader=The current time is

La ressource Français (France) se trouve dans un fichier nommé Strings.fr-FR.txt :

TimeHeader=L'heure actuelle est

La ressource Russe (Russie) se trouve dans un fichier nommé Strings.ru-RU-txt :

TimeHeader=Текущее время —

Le code source de cet exemple provient d’un fichier GetString.cs pour la version C# du code et d’un fichier GetString.vb pour la version Visual Basic. Ce code définit un tableau de chaînes qui contient le nom de quatre cultures : les trois cultures pour lesquelles des ressources sont disponibles et la culture Espagnol (Espagne). Une boucle exécutée cinq fois de façon aléatoire sélectionne l’une de ces cultures et l’affecte aux propriétés Thread.CurrentCulture et CultureInfo.CurrentUICulture. Elle appelle ensuite la méthode GetString(String) pour récupérer la chaîne localisée, qui s’affiche avec l’heure actuelle.

using System;
using System.Globalization;
using System.Resources;
using System.Threading;

[assembly: NeutralResourcesLanguageAttribute("en-US")]

public class Example
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "fr-FR", "ru-RU", "es-ES" };
      Random rnd = new Random();
      ResourceManager rm = new ResourceManager("Strings", 
                               typeof(Example).Assembly);

      for (int ctr = 0; ctr <= cultureNames.Length; ctr++) {
         string cultureName = cultureNames[rnd.Next(0, cultureNames.Length)];
         CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName);
         Thread.CurrentThread.CurrentCulture = culture;
         Thread.CurrentThread.CurrentUICulture = culture;

         Console.WriteLine("Current culture: {0}", culture.NativeName);
         string timeString = rm.GetString("TimeHeader");
         Console.WriteLine("{0} {1:T}\n", timeString, DateTime.Now);   
      }   
   }
}
// The example displays output like the following:
//    Current culture: English (United States)
//    The current time is 9:34:18 AM
//    
//    Current culture: Español (España, alfabetización internacional)
//    The current time is 9:34:18
//    
//    Current culture: русский (Россия)
//    Текущее время — 9:34:18
//    
//    Current culture: français (France)
//    L'heure actuelle est 09:34:18
//    
//    Current culture: русский (Россия)
//    Текущее время — 9:34:18

Le fichier de commandes (.bat) ci-dessous compile l’exemple et génère des assemblys satellites dans les répertoires appropriés. Les commandes indiquées s’appliquent au langage et au compilateur C#. Pour Visual Basic, remplacez csc par vbc, et GetString.cs par GetString.vb.


resgen strings.txt
csc GetString.cs /resource:strings.resources

resgen strings.fr-FR.txt
md fr-FR
al /embed:strings.fr-FR.resources /culture:fr-FR /out:fr-FR\GetString.resources.dll

resgen strings.ru-RU.txt
md ru-RU
al /embed:strings.ru-RU.resources /culture:ru-RU /out:ru-RU\GetString.resources.dll

Quand la culture d’interface utilisateur actuelle est Espagnol (Espagne), l’exemple affiche les ressources en langue anglaise, car les ressources pour l’espagnol ne sont pas disponibles et l’anglais est la culture par défaut définie dans cet exemple.

Vous pouvez utiliser les méthodes GetObject et GetStream pour récupérer des données d’objet. Cela inclut les types de données primitives, les objets sérialisables et les objets qui sont stockés au format binaire (tels que les images).

L’exemple suivant utilise la méthode GetStream(String) pour récupérer une image bitmap qui s’affiche dans la fenêtre de démarrage à l’ouverture d’une application. Le code source ci-dessous provient d’un fichier nommé CreateResources.cs (pour C#) ou CreateResources.vb (pour Visual Basic). Ce code crée un fichier .resx qui contient l’image sérialisée. Dans cet exemple, l’image est chargée à partir d’un fichier SplashScreen.jpg. Vous pouvez remplacer ce nom de fichier par votre image.

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Resources;

public class Example
{
   public static void Main()
   {
      Bitmap bmp = new Bitmap(@".\SplashScreen.jpg");
      MemoryStream imageStream = new MemoryStream();
      bmp.Save(imageStream, ImageFormat.Jpeg);

      ResXResourceWriter writer = new ResXResourceWriter("AppResources.resx");
      writer.AddResource("SplashScreen", imageStream);
      writer.Generate();
      writer.Close();      
   }
}

Le code suivant récupère la ressource et affiche l’image dans un contrôle PictureBox.

using System;
using System.Drawing;
using System.IO;
using System.Resources;
using System.Windows.Forms;

public class Example
{
   public static void Main()
   {
      ResourceManager rm = new ResourceManager("AppResources", typeof(Example).Assembly);
      Bitmap screen = (Bitmap) Image.FromStream(rm.GetStream("SplashScreen"));

      Form frm = new Form();
      frm.Size = new Size(300, 300);

      PictureBox pic = new PictureBox();
      pic.Bounds = frm.RestoreBounds;
      pic.BorderStyle = BorderStyle.Fixed3D; 
      pic.Image = screen;
      pic.SizeMode = PictureBoxSizeMode.StretchImage;

      frm.Controls.Add(pic);
      pic.Anchor = AnchorStyles.Top | AnchorStyles.Bottom |
                   AnchorStyles.Left | AnchorStyles.Right;

      frm.ShowDialog();
   }
}

Vous pouvez utiliser le fichier de commandes suivant pour générer l’exemple C#. Pour Visual Basic, remplacez csc par vbc, et modifiez l’extension du fichier de code source .cs en .vb.


csc CreateResources.cs
CreateResources

resgen AppResources.resx

csc GetStream.cs /resource:AppResources.resources

L’exemple suivant utilise la méthode ResourceManager.GetObject(String) pour désérialiser un objet personnalisé. Il inclut un fichier de code source UIElements.cs (UIElements.vb pour Visual Basic) qui définit la structure suivante nommée PersonTable. Cette structure est ensuite utilisée par une routine d’affichage de table générale qui affiche les noms localisés des colonnes de table. Notez que la structure PersonTable est marquée avec l’attribut SerializableAttribute.

using System;

[Serializable] public struct PersonTable
{
   public readonly int nColumns;
   public readonly string column1; 
   public readonly string column2;
   public readonly string column3; 
   public readonly int width1;
   public readonly int width2;
   public readonly int width3;

   public PersonTable(string column1, string column2, string column3,
                  int width1, int width2, int width3)
   {
      this.column1 = column1;
      this.column2 = column2;
      this.column3 = column3;
      this.width1 = width1;
      this.width2 = width2;
      this.width3 = width3;
      this.nColumns = typeof(PersonTable).GetFields().Length / 2; 
   }
}

Le code ci-dessous provient d’un fichier CreateResources.cs (CreateResources.vb pour Visual Basic). Il crée un fichier de ressources XML nommé UIResources.resx qui stocke un titre de table ainsi qu’un objet PersonTable qui contient des informations relatives à une application localisée en anglais.

using System;
using System.Resources;

public class CreateResource
{
   public static void Main()
   {
      PersonTable table = new PersonTable("Name", "Employee Number", 
                                          "Age", 30, 18, 5);
      ResXResourceWriter rr = new ResXResourceWriter(@".\UIResources.resx");
      rr.AddResource("TableName", "Employees of Acme Corporation");
      rr.AddResource("Employees", table);
      rr.Generate();
      rr.Close();
   }
}

Le code suivant, qui provient d’un fichier de code source nommé GetObject.cs (ou GetObject.vb), récupère ensuite les ressources et les affiche dans la console.

using System;
using System.Resources;

[assembly: NeutralResourcesLanguageAttribute("en")]

public class Example
{
   public static void Main()
   {
      string fmtString = String.Empty;
      ResourceManager rm = new ResourceManager("UIResources", typeof(Example).Assembly);       
      string title = rm.GetString("TableName");
      PersonTable tableInfo = (PersonTable) rm.GetObject("Employees");

      if (! String.IsNullOrEmpty(title)) {
         fmtString = "{0," + ((Console.WindowWidth + title.Length) / 2).ToString() + "}"; 
         Console.WriteLine(fmtString, title);      
         Console.WriteLine();
      }

      for (int ctr = 1; ctr <= tableInfo.nColumns; ctr++) {
         string columnName = "column"  + ctr.ToString();
         string widthName = "width" + ctr.ToString();
         string value = tableInfo.GetType().GetField(columnName).GetValue(tableInfo).ToString();
         int width = (int) tableInfo.GetType().GetField(widthName).GetValue(tableInfo);
         fmtString = "{0,-" + width.ToString() + "}";
         Console.Write(fmtString, value);
      }      
      Console.WriteLine();
   }
}

Vous pouvez créer le fichier et les assemblys de ressources nécessaires, puis lancer l’application en exécutant le fichier de commandes suivant. Vous devez utiliser l’option /r pour fournir à Resgen.exe une référence à UIElements.dll qui lui permet d’accéder aux informations relatives à la structure PersonTable. Si vous utilisez C#, remplacez le nom du compilateur vbc par csc et modifiez l’extension .vb en .cs.


vbc /t:library UIElements.vb
vbc CreateResources.vb /r:UIElements.dll
CreateResources

resgen UIResources.resx  /r:UIElements.dll
vbc GetObject.vb /r:UIElements.dll /resource:UIResources.resources

GetObject.exe

Par défaut, quand l’objet ResourceManager récupère les ressources demandées, il recherche les assemblys satellites dont les numéros de version correspondent au numéro de version de l’assembly principal. Après avoir déployé une application, vous pouvez avoir besoin de mettre à jour l’assembly principal ou des assemblys satellites de ressources spécifiques. .NET Framework prend en charge le contrôle de version pour l’assembly principal et les assemblys satellites.

L’attribut SatelliteContractVersionAttribute fournit la prise en charge du contrôle de version pour un assembly principal. Spécifiez cet attribut sur l’assembly principal d’une application si vous voulez mettre à jour et redéployer un assembly principal sans mettre à jour ses assemblys satellites. Après avoir mis à jour l’assembly principal, incrémentez son numéro de version, mais ne modifiez pas le numéro de version de contrat satellite. Quand le Gestionnaire des ressources récupère les ressources demandées, il charge la version d’assembly satellite spécifiée par cet attribut.

Les assemblys de stratégie de serveur de publication prennent en charge le contrôle de version pour les assemblys satellites. Vous pouvez mettre à jour et redéployer un assembly satellite sans avoir à mettre à jour l’assembly principal. Après la mise à jour d’un assembly satellite, incrémentez son numéro de version et distribuez-le avec un assembly de stratégie de serveur de publication. Dans l’assembly de stratégie de serveur de publication, spécifiez que votre nouvel assembly satellite offre une compatibilité descendante avec sa version précédente. Le Gestionnaire des ressources utilise l’attribut SatelliteContractVersionAttribute pour déterminer la version de l’assembly satellite, mais le chargeur d’assembly établit une liaison à la version d’assembly satellite spécifiée par la stratégie de serveur de publication. Pour plus d’informations sur les assemblys de stratégie de serveur de publication, consultez Création d’un fichier de stratégie de serveur de publication.

Pour garantir une prise en charge totale du contrôle de version des assemblys, nous vous recommandons de déployer les assemblys avec nom fort dans le GAC et de déployer les assemblys sans nom fort dans le répertoire de l’application. Si vous déployez des assemblys avec nom fort dans le répertoire de l’application, vous ne pourrez pas incrémenter le numéro de version d’un assembly satellite lors de la mise à jour de l’assembly principal. Au lieu de cela, vous devez effectuer une mise à jour sur place où vous remplacez le code existant par le code mis à jour et conservez le même numéro de version. Par exemple, si vous souhaitez mettre à jour la version 1.0.0.0 d’un assembly satellite avec le nom d’assembly spécifié entièrement (« myApp.resources, Version = 1.0.0.0, Culture = de, PublicKeyToken = b03f5f11d50a3a »), remplacez-le par le fichier myApp.resources.dll mis à jour qui a été compilé avec le même nom d’assembly spécifié entièrement (« myApp.resources, Version = 1.0.0.0, Culture = de, PublicKeyToken = b03f5f11d50a3a »). Notez que, si vous faites des mises à jour sur place dans les fichiers d’assembly satellite, il est difficile pour une application de déterminer la version exacte d’un assembly satellite.

Pour plus d’informations sur le contrôle de version des assemblys, consultez Versioning des assemblys et Méthode de localisation des assemblys par le runtime.

Si vous choisissez de ne pas déployer de ressources dans des assemblys satellites, vous pouvez utiliser un objet ResourceManager pour accéder directement aux ressources des fichiers .resources. Pour ce faire, vous devez déployer les fichiers .resources correctement. Ensuite, utilisez la méthode ResourceManager.CreateFileBasedResourceManager pour instancier un objet ResourceManager et spécifiez le répertoire qui contient les fichiers .resources autonomes.

Quand vous incorporez des fichiers .resources dans un assembly d’application et des assemblys satellites, chaque assembly satellite porte le même nom de fichier, mais est placé dans un sous-répertoire qui reflète la culture de l’assembly satellite. En revanche, quand vous accédez directement aux ressources de fichiers .resources, vous pouvez placer tous les fichiers .resources dans le même répertoire, généralement un sous-répertoire du répertoire de l’application. Le nom du fichier .resources par défaut de l’application se compose uniquement d’un nom racine, sans indication de sa culture (par exemple, strings.resources). Les ressources de chaque culture localisée sont stockées dans un fichier dont le nom se compose du nom racine suivi de la culture (par exemple, strings.ja.resources ou strings.de-DE.resources). L’illustration suivante montre où placer les fichiers de ressources dans la structure de répertoires.

Répertoire principal de votre application

Structure de répertoires et conventions de nommage pour les fichiers .resources

Une fois que vous avez créé vos ressources et les avez placées dans le répertoire approprié, créez un objet ResourceManager qui utilise ces ressources en appelant la méthode CreateFileBasedResourceManager(String, String, Type). Le premier paramètre spécifie le nom racine du fichier .resources par défaut de l’application (« strings » dans l’exemple de la section précédente). Le deuxième paramètre spécifie l’emplacement des ressources (« Resources » dans l’exemple précédent). Le troisième paramètre spécifie l’implémentation de ResourceSet à utiliser. Si ce paramètre est null, le runtime par défaut ResourceSet est utilisé.

System_CAPS_noteRemarque

Ne déployez pas d’applications ASP.NET à l’aide de fichiers .resources autonomes, car cela peut entraîner des problèmes de verrouillage et l’arrêt du déploiement XCOPY. Nous vous recommandons de déployer les ressources ASP.NET dans des assemblys satellites. Pour plus d'informations, consultez ASP.NET Web Page Resources Overview.

Après avoir instancié l’objet ResourceManager, utilisez les méthodes GetString, GetObject et GetStream pour récupérer les ressources, comme indiqué plus haut. Toutefois, la récupération de ressources directement à partir des fichiers .resources s’effectue différemment de la récupération des ressources incorporées à partir d’assemblys. Quand vous récupérez des ressources de fichiers .resources, les méthodes GetString(String), GetObject(String) et GetStream(String) récupèrent toujours les ressources de la culture par défaut, quelle que soit la culture actuelle. Pour récupérer les ressources de la culture actuelle de l’application ou d’une autre culture, vous devez appeler la méthode GetString(String, CultureInfo), GetObject(String, CultureInfo) ou GetStream(String, CultureInfo) et spécifier la culture pour laquelle les ressources doivent être récupérées. Pour récupérer les ressources de la culture actuelle, spécifiez la valeur de la propriété CultureInfo.CurrentCulture comme argument culture. Si le Gestionnaire des ressources ne peut pas récupérer les ressources de culture, il récupère les ressources appropriées à l’aide des règles de secours standard pour les ressources.

L’exemple suivant montre comment le Gestionnaire des ressources récupère les ressources directement des fichiers .resources. Il utilise trois fichiers de ressources texte pour les cultures Anglais (États-Unis), Français (France) et Russe (Russie). La culture Anglais (États-Unis) est la culture par défaut utilisée dans cet exemple. Ses ressources sont stockées dans le fichier Strings.txt suivant :

Greeting=Hello
Prompt=What is your name?

Les ressources pour la culture Français (France) sont stockées dans le fichier suivant, nommé Strings.fr-FR.txt :

Greeting=Bon jour
Prompt=Comment vous appelez-vous?

Les ressources pour la culture Russe (Russie) sont stockées dans le fichier suivant, nommé Strings.ru-RU.txt :

Greeting=Здравствуйте
Prompt=Как вас зовут?

Voici le code source de l'exemple. L’exemple instancie les objets CultureInfo pour les cultures Anglais (États-Unis), Anglais (Canada), Français (France) et Russe (Russie), et définit chacune d’elles comme culture actuelle. La méthode ResourceManager.GetString(String, CultureInfo) fournit ensuite la valeur de la propriété CultureInfo.CurrentCulture comme argument culture pour récupérer les ressources appropriées de la culture.

using System;
using System.Globalization;
using System.Resources;
using System.Threading;

[assembly: NeutralResourcesLanguage("en-US")]

public class Example
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "en-CA", "ru-RU", "fr-FR" };
      ResourceManager rm = ResourceManager.CreateFileBasedResourceManager("Strings", "Resources", null);

      foreach (var cultureName in cultureNames) {
         Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
         string greeting = rm.GetString("Greeting", CultureInfo.CurrentCulture);
         Console.WriteLine("\n{0}!", greeting);
         Console.Write(rm.GetString("Prompt", CultureInfo.CurrentCulture));
         string name = Console.ReadLine();
         if (! String.IsNullOrEmpty(name))
            Console.WriteLine("{0}, {1}!", greeting, name);
      }
      Console.WriteLine();
   }
}
// The example displays output like the following:
//       Hello!
//       What is your name? Dakota
//       Hello, Dakota!
//       
//       Hello!
//       What is your name? Koani
//       Hello, Koani!
//       
//       Здравствуйте!
//       Как вас зовут?Samuel
//       Здравствуйте, Samuel!
//       
//       Bon jour!
//       Comment vous appelez-vous?Yiska
//       Bon jour, Yiska!

Vous pouvez compiler la version C# de l’exemple en exécutant le fichier de commandes suivant. Si vous utilisez Visual Basic, remplacez csc par vbc et modifiez l’extension .cs en .vb.


Md Resources
Resgen Strings.txt Resources\Strings.resources
Resgen Strings.fr-FR.txt Resources\Strings.fr-FR.resources
Resgen Strings.ru-RU.txt Resources\Strings.ru-RU.resources

csc Example.cs

Afficher: