Classe CultureInfo

Cet article vous fournit des remarques complémentaires à la documentation de référence de cette API.

La classe CultureInfo fournit des informations culturelles spécifiques, telles que le langage, la sous-langue, le pays/la région, le calendrier et les conventions associées à une culture particulière. Cette classe permet également d’accéder à des instances spécifiques à la culture des objets DateTimeFormatInfo, NumberFormatInfo, CompareInfoet TextInfo. Ces objets contiennent les informations nécessaires aux opérations spécifiques à la culture, telles que la casse, le formatage des dates et des nombres et la comparaison de chaînes. La classe CultureInfo est utilisée directement ou indirectement par des classes qui formatent, analysent ou manipulent des données spécifiques à une culture, telles que String, DateTime, DateTimeOffsetet les types numériques.

Noms de culture et identificateurs

La classe CultureInfo spécifie un nom unique pour chaque culture, sur la base du RFC 4646. Le nom est une combinaison d’un code de culture au format ISO 639 composé de deux ou trois lettres minuscules, associé à une langue, et d’un code de sous-culture au format ISO 3166 composé de deux lettres majuscules, associé à un pays ou à une région. En outre, pour les applications qui s’exécutent sous Windows 10 ou version ultérieure, les noms de culture correspondant aux balises de langue BCP-47 valides sont pris en charge.

Remarque

Lorsqu’un nom de culture est transmis à un constructeur de classe ou à une méthode telle que CreateSpecificCulture ou CultureInfo, sa casse n’est pas significative.

Le format du nom de culture basé sur RFC 4646 est languagecode2-country/regioncode2, où languagecode2 est le code de langue à deux lettres et country/regioncode2 est le code de sous-culture à deux lettres. Par exemple, ja-JP pour le japonais (Japon) et en-US pour l’anglais (États-Unis). Dans les cas où un code de langue à deux lettres n’est pas disponible, un code à trois lettres tel que défini dans la norme ISO 639-3 est utilisé.

Certains noms de culture spécifient également un script ISO 15924. Par exemple, Cyrl spécifie l’écriture cyrillique et Latn l’écriture latine. Un nom de culture qui comprend un script utilise le modèle languagecode2-scripttag-country/regioncode2. Un exemple de ce type de nom de culture est uz-Cyrl-UZ pour Ouzbek (cyrillique, Ouzbékistan). Sur les systèmes d’exploitation Windows antérieurs à Windows Vista, un nom de culture comprenant un script utilise le modèle languagecode2-country/regioncode2-scripttag, par exemple, uz-UZ-Cyrl pour Ouzbek (cyrillique, Ouzbékistan).

Une culture neutre est spécifiée uniquement par le code linguistique à deux lettres minuscules. Par exemple, fr spécifie la culture neutre pour le français et de spécifie la culture neutre pour l’allemand.

Remarque

Il existe néanmoins deux noms de culture qui contredisent cette règle. Les cultures chinoises (simplifiées), nommées zh-Hans et chinoises (traditionnelles), nommées zh-Hant, sont des cultures neutres. Les noms de culture représentent la norme actuelle et doivent être utilisés, sauf si vous avez une raison d’utiliser les anciens noms zh-CHS et zh-CHT.

Un identificateur de culture est une abréviation numérique internationale standard et contient les composants nécessaires pour identifier de manière unique l’une des cultures installées. Votre application peut utiliser des identificateurs de culture prédéfinis ou définir des identificateurs personnalisés.

Certains noms de culture et identificateurs prédéfinis sont utilisés par cette classe et d’autres classes de l’espace de noms System.Globalization. Pour obtenir des informations détaillées sur la culture des systèmes Windows, consultez la colonne Balise de langue dans la liste des noms de langue/région pris en charge par Windows. Les noms de culture respectent la norme définie par BCP 47.

Les noms et identifiants de culture représentent seulement un sous-ensemble de cultures qui se trouvent sur un ordinateur spécifique. Les versions de Windows ou les Service Packs peuvent modifier les cultures disponibles. Les applications peuvent ajouter des cultures personnalisées à l’aide de la classe CultureAndRegionInfoBuilder. Les utilisateurs peuvent ajouter leurs propres cultures personnalisées à l’aide de l’outil Microsoft Locale Builder. Microsoft Locale Builder est écrit avec du code managé à l’aide de la classe CultureAndRegionInfoBuilder.

Plusieurs noms distincts sont étroitement associés à une culture, notamment les noms associés aux membres de la classe suivants :

Cultures invariantes, neutres et spécifiques

Les cultures sont généralement regroupées en trois ensembles : les cultures invariantes, les cultures neutres et les cultures spécifiques.

Une culture invariante ne tient pas compte de la culture. Votre application spécifie la culture invariante par nom en utilisant une chaîne vide («  ») ou par son identificateur. InvariantCulture définit une instance de la culture invariante. Celle-ci est associée à la langue anglaise, mais pas à un pays ou à une région. Elle est utilisée dans presque toutes les méthodes de l’espace de nom Globalization qui nécessite une culture.

Une culture neutre est une culture associée à une langue mais pas à un pays ou une région. Une culture spécifique est une culture associée à une langue et à un pays ou une région. Par exemple, fr est le nom neutre de la culture française et fr-FR est le nom de la culture française (France) spécifique. Notez que le chinois (simplifié) et le chinois (traditionnel) sont également considérés comme des cultures neutres.ent considérés comme des cultures neutres.

Nous déconseillons la création d’une instance de classe CompareInfo pour une culture neutre, car les données qu’elle contient sont arbitraires. Si vous souhaitez afficher et trier des données, vous devez spécifier la langue et la région. Par ailleurs, la propriété Name d’un objet CompareInfo créé pour une culture neutre retourne uniquement le pays et n’inclut pas la région.

Les cultures définies ont une hiérarchie dans laquelle le parent d’une culture spécifique est une culture neutre et le parent d’une culture neutre est la culture invariante. La propriété Parent contient la culture neutre associée à une culture spécifique. Les cultures personnalisées doivent définir la propriété Parent conformément à ce modèle.

Si les ressources d’une culture spécifique ne sont pas disponibles dans le système d’exploitation, celui-ci utilisera les ressources de la culture neutre associée. Si les ressources pour la culture neutre ne sont pas disponibles, ce seront les ressources intégrées dans l’assembly principal qui seront utilisées. Pour plus d’informations sur le processus de substitution des ressources, consultez Empaquetage et déploiement des ressources.

La liste des paramètres régionaux de l’API Windows est légèrement différente de la liste des cultures prises en charge par .NET. Si l’interopérabilité avec Windows est nécessaire, par exemple au moyen du mécanisme p/invoke, l’application doit utiliser une culture spécifique définie pour le système d’exploitation. L’utilisation de la culture spécifique garantit la cohérence avec le paramètre régional équivalent de Windows, qui est identifié par un identificateur de paramètre régional identique à LCID.

Une DateTimeFormatInfo ou une NumberFormatInfo peut être créée uniquement pour la culture invariante ou pour des cultures spécifiques, mais pas pour des cultures neutres.

Si DateTimeFormatInfo.Calendar est la TaiwanCalendar mais que Thread.CurrentCulture n’est pas définie sur zh-TW, alors DateTimeFormatInfo.NativeCalendarName, DateTimeFormatInfo.GetEraNameet DateTimeFormatInfo.GetAbbreviatedEraName retournent une chaîne vide («  »).

Cultures personnalisées

Sous Windows, vous pouvez créer des paramètres régionaux personnalisés. Pour plus d’informations, consultez Paramètres régionaux personnalisés.

CultureInfo et données culturelles

.NET puise ses données culturelles auprès de diverses sources, en fonction de l’implémentation, de la plateforme et de la version :

  • Pour toutes les versions de .NET (Core) exécutées sur des plateformes Unix ou Windows 10 et versions ultérieures, les données culturelles sont fournies par la bibliothèque International Components for Unicode (ICU). La version précise de la bibliothèque ICU dépend des spécificités de chaque système d’exploitation.
  • Pour toutes les versions de .NET (Core) exécutées sur Windows 9 et versions antérieures, les données culturelles sont fournies par le système d’exploitation Windows.
  • Pour .NET Framework 4 et versions ultérieures, les données culturelles sont fournies par le système d’exploitation Windows.

Pour cette raison, une culture disponible sur une implémentation, une plateforme ou une version particulière de .NET peut ne pas être disponible sur une implémentation, une plateforme ou une version différente de .NET.

Certains objets CultureInfo diffèrent selon la plateforme sous-jacente. Notamment, zh-CN, ou le chinois (simplifié, Chine) et zh-TW, ou le chinois (traditionnel, Taïwan), sont des cultures disponibles sur les systèmes Windows, mais ce sont des cultures avec un alias sur les systèmes Unix. « zh-CN » est un alias de la culture « zh-Hans-CN », et « zh-TW » est un alias de la culture « zh-Hant-TW ». Les cultures avec un alias ne sont pas retournées par les appels à la méthode GetCultures et peuvent avoir des valeurs de propriété différentes, y compris des cultures Parentdifférentes, que leurs homologues Windows. Pour les cultures zh-CN et zh-TW, ces différences sont les suivantes :

  • Sur les systèmes Windows, la culture parente de la culture « zh-CN » est « zh-Hans », et la culture parente de la culture « zh-TW » est « zh-Hant ». La culture parente de ces deux cultures est « zh ». Sur les systèmes Unix, les parents des deux cultures sont « zh ». Autrement dit, si vous ne fournissez pas de ressources spécifiques aux cultures « zh-CN » ou « zh-TW » mais que vous fournissez des ressources pour la culture neutre « zh-Hans » ou « zh-Hant », votre application chargera les ressources pour la culture neutre sous Windows mais pas sous Unix. Sur les systèmes Unix, vous devez définir explicitement les CurrentUICulture du thread sur « zh-Hans » ou « zh-Hant ».

  • Sur les systèmes Windows, appeler CultureInfo.Equals sur une instance qui représente la culture « zh-CN » et lui associer une instance « zh-Hans-CN » retourne true. Sur les systèmes Unix, l’appel de méthode retourne false. Ce comportement s’applique également à l’appel de Equals sur une instance CultureInfo « zh-TW » et à la transmission d’une instance « zh-Hant-Tw ».

Données de culture dynamique

À l’exception de la culture invariante, les données de culture sont dynamiques. Cela est également applicable aux cultures prédéfinies. Par exemple, des pays ou des régions adoptent de nouvelles monnaies, modifient l’orthographe de certains mots ou changent de calendrier, et les définitions de culture évoluent pour tenir compte de ces modifications. Les cultures personnalisées peuvent être modifiées sans préavis et toute culture spécifique peut être remplacée par une culture de substitution personnalisée. En outre, comme indiqué ci-dessous, un utilisateur individuel peut remplacer les préférences culturelles. Les applications doivent toujours obtenir des données de culture au moment de l’exécution.

Attention

Lors de l’enregistrement des données, votre application doit utiliser la culture invariante, un format binaire ou un format spécifique indépendant de la culture. Les données enregistrées selon les valeurs courantes associées à une culture particulière, autre que la culture invariante, peuvent devenir illisibles ou changer de signification si cette culture change.

Culture actuelle et culture actuelle de l’interface utilisateur

Chaque thread d’une application .NET possède une culture actuelle et une culture actuelle de l’interface utilisateur. La culture actuelle détermine les conventions de formatage pour les dates, les heures, les nombres et les valeurs monétaires, l’ordre de tri du texte, les conventions de mise en majuscules et la manière dont les chaînes de caractères sont comparées. La culture actuelle de l’interface utilisateur est utilisée pour récupérer les ressources spécifiques à la culture au moment de l’exécution.

Remarque

Pour plus d’informations sur la manière dont la culture actuelle et la culture actuelle de l’interface utilisateur sont déterminées pour chaque thread, consultez la section Culture et threads. Pour plus d’informations sur la manière dont la culture actuelle et la culture actuelle de l’interface utilisateur sont déterminées sur les threads qui s’exécutent dans un nouveau domaine d’application et sur les threads qui dépassent les limites des domaines d’application, consultez la section Culture et domaines d’application. Pour plus d’informations sur la manière dont la culture actuelle et la culture actuelle de l’interface utilisateur sont déterminées sur les threads effectuant des opérations asynchrones basées sur des tâches, consultez la section Culture et opérations asynchrones basées sur des tâches.

Pour obtenir des informations plus détaillées sur la culture actuelle, reportez-vous à la propriété CultureInfo.CurrentCulture. Pour obtenir des informations plus détaillées sur la culture actuelle de l’interface utilisateur, reportez-vous à la rubrique dédiée à la propriété CultureInfo.CurrentUICulture.

Récupérer la culture actuelle et la culture actuelle de l’interface utilisateur

Pour obtenir un objet CultureInfo représentant la culture actuelle, deux possibilités s’offrent à vous :

L’exemple suivant récupère les deux valeurs des propriétés, les compare pour montrer qu’elles sont égales et affiche le nom de la culture actuelle.

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

public class CurrentCultureEx
{
    public static void Main()
    {
        CultureInfo culture1 = CultureInfo.CurrentCulture;
        CultureInfo culture2 = Thread.CurrentThread.CurrentCulture;
        Console.WriteLine("The current culture is {0}", culture1.Name);
        Console.WriteLine("The two CultureInfo objects are equal: {0}",
                          culture1 == culture2);
    }
}
// The example displays output like the following:
//     The current culture is en-US
//     The two CultureInfo objects are equal: True

Pour obtenir un objet CultureInfo représentant la culture actuelle de l’interface utilisateur, deux possibilités s’offrent à vous :

L’exemple suivant récupère les deux valeurs des propriétés, les compare pour vérifier si elles sont égales et affiche le nom de la culture actuelle de l’interface utilisateur.

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

public class CurrentUIEx
{
    public static void Main()
    {
        CultureInfo uiCulture1 = CultureInfo.CurrentUICulture;
        CultureInfo uiCulture2 = Thread.CurrentThread.CurrentUICulture;
        Console.WriteLine("The current UI culture is {0}", uiCulture1.Name);
        Console.WriteLine("The two CultureInfo objects are equal: {0}",
                          uiCulture1 == uiCulture2);
    }
}
// The example displays output like the following:
//     The current UI culture is en-US
//     The two CultureInfo objects are equal: True

Définir la culture actuelle et la culture courante de l’interface utilisateur

Pour modifier la culture et la culture de l’interface utilisateur d’un thread, procédez de la manière suivante :

  1. Instanciez un objet CultureInfo qui représente cette culture en appelant un constructeur de classe CultureInfo et en lui transmettant le nom de la culture. Le constructeur CultureInfo(String) instancie un objet CultureInfo qui reflète les modifications apportées par l’utilisateur si la nouvelle culture est la même que la culture Windows actuelle. Le constructeur CultureInfo(String, Boolean) vous permet de spécifier si l’objet CultureInfo nouvellement instancié reflète les substitutions de l’utilisateur si la nouvelle culture est la même que la culture Windows actuelle.

  2. Assignez l’objet CultureInfo à la propriété CultureInfo.CurrentCulture ou CultureInfo.CurrentUICulture sur .NET Core et .NET Framework 4.6 et versions ultérieures.

L’exemple suivant permet de récupérer la culture actuelle. S’il s’agit d’une autre culture que la culture française (France), la culture actuelle devient la culture française (France). Dans le cas contraire, la culture actuelle devient la culture française (Luxembourg).

using System;
using System.Globalization;

public class ChangeEx1
{
    public static void Main()
    {
        CultureInfo current = CultureInfo.CurrentCulture;
        Console.WriteLine("The current culture is {0}", current.Name);
        CultureInfo newCulture;
        if (current.Name.Equals("fr-FR"))
            newCulture = new CultureInfo("fr-LU");
        else
            newCulture = new CultureInfo("fr-FR");

        CultureInfo.CurrentCulture = newCulture;
        Console.WriteLine("The current culture is now {0}",
                          CultureInfo.CurrentCulture.Name);
    }
}
// The example displays output like the following:
//     The current culture is en-US
//     The current culture is now fr-FR

L’exemple suivant permet de récupérer la culture actuelle. S’il s’agit d’une autre culture que la culture slovène (Slovénie), la culture actuelle devient la culture slovène (Slovénie). Dans le cas contraire, la culture actuelle est remplacée par la culture croate (Croatie).

using System;
using System.Globalization;

public class ChangeUICultureEx
{
    public static void Main()
    {
        CultureInfo current = CultureInfo.CurrentUICulture;
        Console.WriteLine("The current UI culture is {0}", current.Name);
        CultureInfo newUICulture;
        if (current.Name.Equals("sl-SI"))
            newUICulture = new CultureInfo("hr-HR");
        else
            newUICulture = new CultureInfo("sl-SI");

        CultureInfo.CurrentUICulture = newUICulture;
        Console.WriteLine("The current UI culture is now {0}",
                          CultureInfo.CurrentUICulture.Name);
    }
}
// The example displays output like the following:
//     The current UI culture is en-US
//     The current UI culture is now sl-SI

Obtenir toutes les cultures

Vous pouvez récupérer un tableau de catégories spécifiques de cultures ou de toutes les cultures disponibles sur l’ordinateur local en appelant la méthode GetCultures. Par exemple, vous pouvez récupérer des cultures personnalisées, des cultures spécifiques ou des cultures neutres, seules ou combinées.

L’exemple suivant appelle la méthode GetCultures deux fois, d’abord avec le membre d’énumération System.Globalization.CultureTypes pour récupérer toutes les cultures personnalisées, puis avec le membre d’énumération System.Globalization.CultureTypes pour récupérer toutes les cultures de substitution.

using System;
using System.Globalization;

public class GetCulturesEx
{
    public static void Main()
    {
        // Get all custom cultures.
        CultureInfo[] custom = CultureInfo.GetCultures(CultureTypes.UserCustomCulture);
        if (custom.Length == 0)
        {
            Console.WriteLine("There are no user-defined custom cultures.");
        }
        else
        {
            Console.WriteLine("Custom cultures:");
            foreach (var culture in custom)
                Console.WriteLine("   {0} -- {1}", culture.Name, culture.DisplayName);
        }
        Console.WriteLine();

        // Get all replacement cultures.
        CultureInfo[] replacements = CultureInfo.GetCultures(CultureTypes.ReplacementCultures);
        if (replacements.Length == 0)
        {
            Console.WriteLine("There are no replacement cultures.");
        }
        else
        {
            Console.WriteLine("Replacement cultures:");
            foreach (var culture in replacements)
                Console.WriteLine("   {0} -- {1}", culture.Name, culture.DisplayName);
        }
        Console.WriteLine();
    }
}
// The example displays output like the following:
//     Custom cultures:
//        x-en-US-sample -- English (United States)
//        fj-FJ -- Boumaa Fijian (Viti)
//
//     There are no replacement cultures.

Culture et threads

Lorsqu’un nouveau thread d’application est démarré, sa culture actuelle et la culture actuelle de l’interface utilisateur sont définies par la culture actuelle du système, et non pas par la culture actuelle du thread. L'exemple suivant illustre la différence. Elle définit la culture actuelle et la culture actuelle de l’interface utilisateur d’une application comme étant la culture française (France fr-FR). Si la culture actuelle est déjà fr-FR, l’exemple la remplace par la culture anglaise (États-Unis en-US). Trois nombres aléatoires sont affichés en tant que valeurs monétaires, puis un nouveau thread est créé, qui affiche à son tour trois autres nombres aléatoires en tant que valeurs monétaires. Cependant, comme le montre l’exemple, les valeurs monétaires affichées par le nouveau thread ne reflètent pas les conventions de formatage de la culture française (France), contrairement à la sortie du thread de l’application principale.

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

public class DefaultThreadEx
{
    static Random rnd = new Random();

    public static void Main()
    {
        if (Thread.CurrentThread.CurrentCulture.Name != "fr-FR")
        {
            // If current culture is not fr-FR, set culture to fr-FR.
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("fr-FR");
            Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("fr-FR");
        }
        else
        {
            // Set culture to en-US.
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
            Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("en-US");
        }
        ThreadProc();

        Thread worker = new Thread(ThreadProc);
        worker.Name = "WorkerThread";
        worker.Start();
    }

    private static void DisplayThreadInfo()
    {
        Console.WriteLine("\nCurrent Thread Name: '{0}'",
                          Thread.CurrentThread.Name);
        Console.WriteLine("Current Thread Culture/UI Culture: {0}/{1}",
                          Thread.CurrentThread.CurrentCulture.Name,
                          Thread.CurrentThread.CurrentUICulture.Name);
    }

    private static void DisplayValues()
    {
        // Create new thread and display three random numbers.
        Console.WriteLine("Some currency values:");
        for (int ctr = 0; ctr <= 3; ctr++)
            Console.WriteLine("   {0:C2}", rnd.NextDouble() * 10);
    }

    private static void ThreadProc()
    {
        DisplayThreadInfo();
        DisplayValues();
    }
}
// The example displays output similar to the following:
//       Current Thread Name: ''
//       Current Thread Culture/UI Culture: fr-FR/fr-FR
//       Some currency values:
//          8,11 €
//          1,48 €
//          8,99 €
//          9,04 €
//
//       Current Thread Name: 'WorkerThread'
//       Current Thread Culture/UI Culture: en-US/en-US
//       Some currency values:
//          $6.72
//          $6.35
//          $2.90
//          $7.72

Vous pouvez définir la culture et la culture de l’interface utilisateur de tous les threads d’un domaine d’application en attribuant un objet CultureInfo qui représente cette culture aux propriétés DefaultThreadCurrentCulture et DefaultThreadCurrentUICulture. L’exemple suivant utilise ces propriétés pour s’assurer que tous les threads du domaine d’application par défaut partagent la même culture.

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

public class SetThreadsEx
{
    static Random rnd = new Random();

    public static void Main()
    {
        if (Thread.CurrentThread.CurrentCulture.Name != "fr-FR")
        {
            // If current culture is not fr-FR, set culture to fr-FR.
            CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture("fr-FR");
            CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture("fr-FR");
        }
        else
        {
            // Set culture to en-US.
            CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
            CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture("en-US");
        }
        ThreadProc();

        Thread worker = new Thread(SetThreadsEx.ThreadProc);
        worker.Name = "WorkerThread";
        worker.Start();
    }

    private static void DisplayThreadInfo()
    {
        Console.WriteLine("\nCurrent Thread Name: '{0}'",
                          Thread.CurrentThread.Name);
        Console.WriteLine("Current Thread Culture/UI Culture: {0}/{1}",
                          Thread.CurrentThread.CurrentCulture.Name,
                          Thread.CurrentThread.CurrentUICulture.Name);
    }

    private static void DisplayValues()
    {
        // Create new thread and display three random numbers.
        Console.WriteLine("Some currency values:");
        for (int ctr = 0; ctr <= 3; ctr++)
            Console.WriteLine("   {0:C2}", rnd.NextDouble() * 10);
    }

    private static void ThreadProc()
    {
        DisplayThreadInfo();
        DisplayValues();
    }
}
// The example displays output similar to the following:
//       Current Thread Name: ''
//       Current Thread Culture/UI Culture: fr-FR/fr-FR
//       Some currency values:
//          6,83 €
//          3,47 €
//          6,07 €
//          1,70 €
//
//       Current Thread Name: 'WorkerThread'
//       Current Thread Culture/UI Culture: fr-FR/fr-FR
//       Some currency values:
//          9,54 €
//          9,50 €
//          0,58 €
//          6,91 €

Avertissement

Même si les propriétés DefaultThreadCurrentCulture et DefaultThreadCurrentUICulture sont des membres statiques, elles définissent la culture par défaut et la culture par défaut de l’interface utilisateur uniquement pour le domaine d’application en cours au moment où les valeurs de ces propriétés sont définies. Pour plus d’informations, reportez-vous à la section suivante, Culture et domaines d’application.

Lorsque vous assignez des valeurs aux propriétés DefaultThreadCurrentCulture et DefaultThreadCurrentUICulture, la culture et la culture de l’interface utilisateur des threads du domaine d’application sont également modifiées si aucune culture ne leur a été explicitement assignée. Toutefois, ces threads reflètent les nouveaux paramètres de culture uniquement lorsqu’ils s’exécutent dans le domaine d’application actuel. Si ces threads s’exécutent dans un autre domaine d’application, leur culture devient la culture par défaut définie pour ce domaine d’application. Nous recommandons donc de toujours définir la culture du thread principal de l’application et de ne pas se baser sur les propriétés DefaultThreadCurrentCulture et DefaultThreadCurrentUICulture pour la modifier.

Culture et domaines d’application

DefaultThreadCurrentCulture et DefaultThreadCurrentUICulture sont des propriétés statiques qui définissent explicitement une culture par défaut uniquement pour le domaine d’application courant lorsque la valeur de la propriété est définie ou récupérée. L’exemple suivant définit la culture par défaut et la culture de l’interface utilisateur par défaut du domaine d’application par défaut en français (France), puis utilise la classe AppDomainSetup et le délégué AppDomainInitializer pour définir la culture par défaut et la culture de l’interface utilisateur d’un nouveau domaine d’application en russe (Russie). Un thread unique exécute alors deux méthodes dans chaque domaine d’application. Notez que la culture et la culture de l’interface utilisateur du thread ne sont pas explicitement définies ; elles sont dérivées de la culture et de la culture de l’interface utilisateur par défaut du domaine d’application dans lequel le thread s’exécute. Notez également que les propriétés DefaultThreadCurrentCulture et DefaultThreadCurrentUICulture retournent les valeurs CultureInfo par défaut du domaine d’application en cours au moment de l’appel de méthode.

using System;
using System.Globalization;

public class Example
{
    public static void Main()
    {
        // Set the default culture and display the current date in the current application domain.
        Info info1 = new Info();
        SetAppDomainCultures("fr-FR");

        // Create a second application domain.
        AppDomainSetup setup = new AppDomainSetup();
        setup.AppDomainInitializer = SetAppDomainCultures;
        setup.AppDomainInitializerArguments = new string[] { "ru-RU" };
        AppDomain domain = AppDomain.CreateDomain("Domain2", null, setup);
        // Create an Info object in the new application domain.
        Info info2 = (Info)domain.CreateInstanceAndUnwrap(typeof(Example).Assembly.FullName,
                                                           "Info");

        // Execute methods in the two application domains.
        info2.DisplayDate();
        info2.DisplayCultures();

        info1.DisplayDate();
        info1.DisplayCultures();
    }

    public static void SetAppDomainCultures(string[] names)
    {
        SetAppDomainCultures(names[0]);
    }

    public static void SetAppDomainCultures(string name)
    {
        try
        {
            CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture(name);
            CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture(name);
        }
        // If an exception occurs, we'll just fall back to the system default.
        catch (CultureNotFoundException)
        {
            return;
        }
        catch (ArgumentException)
        {
            return;
        }
    }
}

public class Info : MarshalByRefObject
{
    public void DisplayDate()
    {
        Console.WriteLine("Today is {0:D}", DateTime.Now);
    }

    public void DisplayCultures()
    {
        Console.WriteLine("Application domain is {0}", AppDomain.CurrentDomain.Id);
        Console.WriteLine("Default Culture: {0}", CultureInfo.DefaultThreadCurrentCulture);
        Console.WriteLine("Default UI Culture: {0}", CultureInfo.DefaultThreadCurrentUICulture);
    }
}
// The example displays the following output:
//       Today is 14 октября 2011 г.
//       Application domain is 2
//       Default Culture: ru-RU
//       Default UI Culture: ru-RU
//       Today is vendredi 14 octobre 2011
//       Application domain is 1
//       Default Culture: fr-FR
//       Default UI Culture: fr-FR

Pour plus d’informations sur les cultures et les domaines d’application, reportez-vous à la section « Domaines d’application et threads » de la rubrique Domaines d’application.

Culture et opérations asynchrones basées sur les tâches

Le modèle de programmation asynchrone basé sur les tâches utilise des objets Task et Task<TResult> pour exécuter de manière asynchrone des délégués sur des threads du pool de threads. Le thread spécifique sur lequel une tâche particulière s’exécute n’est pas connu à l’avance, mais est déterminé uniquement au moment de l’exécution.

Pour les applications qui utilisent .NET Framework 4.6 ou une version ultérieure, la culture fait partie du contexte d’une opération asynchrone. Autrement dit, les opérations asynchrones héritent par défaut des valeurs des propriétés CurrentCulture et CurrentUICulture du thread à partir duquel elles sont lancées. Si la culture actuelle ou la culture actuelle de l’interface utilisateur est différente de la culture du système, la culture actuelle dépasse les limites des threads et devient la culture actuelle du thread du pool de threads qui exécute une opération asynchrone.

L'exemple suivant illustre cette situation de façon simple. L’exemple définit un délégué Func<TResult>, formatDelegate, qui retourne des nombres mis en forme en tant que valeurs monétaires. L’exemple modifie la culture actuelle du système en français (France) ou, si le français (France) est déjà la culture actuelle, en anglais (États-Unis). Alors :

  • Appelle directement le délégué pour qu’il s’exécute de manière synchrone sur le thread principal de l’application.
  • Crée une tâche qui exécute le délégué de manière asynchrone sur un thread du pool de threads.
  • Crée une tâche qui exécute le délégué de manière synchrone sur le thread principal de l’application en appelant la méthode Task.RunSynchronously.

Comme le montre la sortie de l’exemple, lorsque la culture actuelle est modifiée en français (France), la culture actuelle de la discussion à partir de laquelle les tâches sont invoquées de manière asynchrone devient la culture actuelle pour cette opération asynchrone.

using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;

public class AsyncCultureEx1
{
    public static void Main()
    {
        decimal[] values = { 163025412.32m, 18905365.59m };
        string formatString = "C2";

        string FormatDelegate()
        {
            string output = $"Formatting using the {CultureInfo.CurrentCulture.Name} " +
            "culture on thread {Thread.CurrentThread.ManagedThreadId}.\n";
            foreach (decimal value in values)
                output += $"{value.ToString(formatString)}   ";

            output += Environment.NewLine;
            return output;
        }

        Console.WriteLine($"The example is running on thread {Thread.CurrentThread.ManagedThreadId}");
        // Make the current culture different from the system culture.
        Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}");
        if (CultureInfo.CurrentCulture.Name == "fr-FR")
            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
        else
            Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");

        Console.WriteLine($"Changed the current culture to {CultureInfo.CurrentCulture.Name}.\n");

        // Execute the delegate synchronously.
        Console.WriteLine("Executing the delegate synchronously:");
        Console.WriteLine(FormatDelegate());

        // Call an async delegate to format the values using one format string.
        Console.WriteLine("Executing a task asynchronously:");
        var t1 = Task.Run(FormatDelegate);
        Console.WriteLine(t1.Result);

        Console.WriteLine("Executing a task synchronously:");
        var t2 = new Task<string>(FormatDelegate);
        t2.RunSynchronously();
        Console.WriteLine(t2.Result);
    }
}
// The example displays the following output:
//         The example is running on thread 1
//         The current culture is en-US
//         Changed the current culture to fr-FR.
//
//         Executing the delegate synchronously:
//         Formatting using the fr-FR culture on thread 1.
//         163 025 412,32 €   18 905 365,59 €
//
//         Executing a task asynchronously:
//         Formatting using the fr-FR culture on thread 3.
//         163 025 412,32 €   18 905 365,59 €
//
//         Executing a task synchronously:
//         Formatting using the fr-FR culture on thread 1.
//         163 025 412,32 €   18 905 365,59 €

DefaultThreadCurrentCulture et DefaultThreadCurrentUICulture sont des propriétés par domaine d’application, c’est-à-dire qu’elles établissent une culture par défaut pour tous les threads qui ne sont pas explicitement assignés à une culture dans un domaine d’application spécifique. Toutefois, pour les applications qui ciblent .NET Framework 4.6 ou une version ultérieure, la culture du thread appelant fait toujours partie du contexte d’une tâche asynchrone, même si la tâche franchit les limites du domaine de l’application.

Sérialisation d’objets CultureInfo

Lorsqu’un objet CultureInfo est sérialisé, tout ce qui est réellement stocké est Name et UseUserOverride. Il est correctement désérialisé uniquement dans un environnement où ce Name a la même signification. Les trois exemples suivants illustrent pourquoi ce n’est pas toujours le cas :

  • Si la valeur de la propriété CultureTypes est CultureTypes.InstalledWin32Cultures, et si cette culture a été introduite pour la première fois dans une version particulière du système d’exploitation Windows, il ne sera pas possible de la désérialiser sur une version antérieure de Windows. Par exemple, si une culture a été introduite dans Windows 10, elle ne peut pas être désérialisée sous Windows 8.

  • Si la valeur CultureTypes est CultureTypes.UserCustomCulture, et que l’ordinateur sur lequel elle est désérialisée ne dispose pas de cette culture personnalisée de l’utilisateur, il n’est pas possible de la désérialiser.

  • Si la valeur CultureTypes est CultureTypes.ReplacementCultures, et que l’ordinateur sur lequel elle est désérialisée n’a pas cette culture de substitution, elle se désérialise avec le même nom, mais pas toutes les mêmes caractéristiques. Par exemple, si en-US est une culture de substitution sur l’ordinateur A, mais pas sur l’ordinateur B, et si un objet CultureInfo qui fait référence à cette culture est sérialisé sur l’ordinateur A et désérialisé sur l’ordinateur B, aucune des caractéristiques personnalisées de la culture n’est transmise. La culture est désérialisée correctement, mais avec une signification différente.

Substitutions du Panneau de configuration

L’utilisateur peut choisir de remplacer certaines des valeurs associées à la culture actuelle de Windows par les options régionales et linguistiques du Panneau de configuration. Par exemple, l’utilisateur peut choisir d’afficher la date dans un format différent ou d’utiliser une devise différente de la devise par défaut de la culture. En général, vos applications doivent respecter les substitutions de l’utilisateur.

Si UseUserOverride est true et que la culture spécifiée correspond à la culture actuelle de Windows, la CultureInfo utilise ces substitutions, y compris les paramètres utilisateur pour les propriétés de l’instance DateTimeFormatInfo retournées par la propriété DateTimeFormat, et les propriétés de l’instance NumberFormatInfo retournées par la propriété NumberFormat. Si les paramètres de l’utilisateur ne sont pas compatibles avec la culture associée à l’CultureInfo par exemple si le calendrier sélectionné ne fait pas partie de l’élément OptionalCalendars, les résultats des méthodes et les valeurs des propriétés sont indéfinis.

Ordres de tri alternatifs

Certaines cultures prennent en charge plusieurs ordres de tri. Par exemple :

  • La culture espagnole (Espagne) dispose de deux ordres de tri : l’ordre de tri international par défaut et l’ordre de tri traditionnel. Lorsque vous instanciez un objet CultureInfo avec le nom de la culture es-ES, l’ordre de tri international est utilisé. Lorsque vous instanciez un objet CultureInfo avec le nom de la culture es-ES-tradnl, l’ordre de tri traditionnel est utilisé.

  • La culture zh-CN (chinois (simplifié, RPC)) prend en charge deux ordres de tri : par prononciation (par défaut) et par nombre de traits. Lorsque vous instanciez un objet CultureInfo avec le nom de la culture zh-CN, l’ordre de tri par défaut est utilisé. Lorsque vous instanciez un objet CultureInfo avec un identificateur local défini à 0x00020804, les chaînes de caractères sont triées en fonction du nombre de traits.

Le tableau suivant répertorie les cultures qui prennent en charge les ordres de tri alternatifs et les identifiants des ordres de tri par défaut et alternatifs.

Nom de culture culture Nom et identificateur de tri par défaut Nom et identificateur de tri alternatif
es-ES Espagnol (Espagne) International : 0x00000C0A Traditionnel : 0x0000040A
zh-TW Chinois (Taïwan) Nombre de traits : 0x00000404 Bopomofo : 0x00030404
zh-CN Chinois (RPC) Prononciation : 0x00000804 Nombre de traits : 0x00020804
zh-HK Chinois (Hong Kong R.A.S.) Nombre de traits : 0x00000c04 Nombre de traits : 0x00020c04
zh-SG Chinese (Singapore) Prononciation : 0x00001004 Nombre de traits : 0x00021004
zh-MO Chinese (Macao (R.A.S.)) Prononciation : 0x00001404 Nombre de traits : 0x00021404
ja-JP Japonais (Japon) Valeur par défaut : 0x00000411 Unicode : 0x00010411
ko-KR Coréen (Corée) Valeur par défaut : 0x00000412 Coréen Xwansung – Unicode : 0x00010412
de-DE Allemand (Allemagne) Dictionnaire : 0x00000407 Annuaire téléphonique DIN de tri : 0x00010407
hu-HU Hongrois (Hongrie) Valeur par défaut : 0x0000040e Tri technique : 0x0001040e
ka-GE Géorgien (Géorgie) Traditionnel : 0x00000437 Tri moderne : 0x00010437

La culture actuelle et les applications UWP

Dans les applications de la plateforme Windows universelle (UWP), les propriétés CurrentCulture et CurrentUICulture sont en lecture-écriture, tout comme dans les applications .NET Framework et .NET Core. Toutefois, les applications UWP reconnaissent une culture unique. Les propriétés CurrentCulture et CurrentUICulture mappées à la première valeur de la collection Windows.ApplicationModel.Resources.Core.ResourceManager.DefaultContext.Languages.

Dans les applications .NET, la culture actuelle est un paramètre par thread, et les propriétés CurrentCulture et CurrentUICulture reflètent uniquement la culture et la culture de l’interface utilisateur du thread actuel. Dans les applications UWP, la culture actuelle est mappée à la collection Windows.ApplicationModel.Resources.Core.ResourceManager.DefaultContext.Languages, qui est un paramètre universel. En définissant la propriété CurrentCulture ou CurrentUICulture, vous modifiez la culture de l’application dans son ensemble ; la culture ne peut pas être définie au niveau de chaque thread.