web-dev-qa-db-fra.com

Existe-t-il un moyen de définir la culture pour toute une application? Tous les threads actuels et les nouveaux threads?

Existe-t-il un moyen de définir la culture pour une application complète? Tous les threads actuels et nouveaux?

Nous avons le nom de la culture stockée dans une base de données et lorsque notre application démarre, nous le faisons.

CultureInfo ci = new CultureInfo(theCultureString);
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;

Mais, bien sûr, cela est "perdu" lorsque nous voulons faire quelque chose dans un nouveau fil. Existe-t-il un moyen de définir CurrentCulture et CurrentUICulture pour l’ensemble de l’application? Pour que les nouveaux fils acquièrent aussi cette culture? Ou est-ce un événement déclenché chaque fois qu'un nouveau thread est créé auquel je peux me connecter?

171
Svish

Dans .NET 4.5, vous pouvez utiliser le CultureInfo.DefaultThreadCurrentCulture propriété pour changer la culture d'un AppDomain.

Pour les versions antérieures à la version 4.5, vous devez utiliser la réflexion pour manipuler la culture d'un AppDomain. Il y a un champ statique privé sur CultureInfo (m_userDefaultCulture dans .NET 2.0 mscorlib, s_userDefaultCulture dans .NET 4.0 mscorlib) qui contrôle ce que CurrentCulture renvoie si un thread n’a pas défini cette propriété sur lui-même.

Cela ne modifie pas les paramètres régionaux du thread natif et ce n'est probablement pas une bonne idée d'envoyer du code qui modifie la culture de cette manière. Cela peut être utile pour tester cependant.

189
Austin

Cela se pose souvent. En gros, non, pas pour .NET 4.0. Vous devez le faire manuellement au début de chaque nouveau thread (ou de la fonction ThreadPool.). Vous pourriez peut-être stocker le nom de la culture (ou simplement l'objet de la culture) dans un champ statique pour éviter de devoir toucher la base de données, mais c'est à peu près tout.

36
Marc Gravell

Si vous utilisez des ressources, vous pouvez le forcer manuellement en:

Resource1.Culture = new System.Globalization.CultureInfo("fr"); 

Dans le gestionnaire de ressources, il existe un code généré automatiquement qui se présente comme suit:

/// <summary>
///   Overrides the current thread's CurrentUICulture property for all
///   resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
    get {
        return resourceCulture;
    }
    set {
        resourceCulture = value;
    }
}

Désormais, chaque fois que vous faites référence à votre chaîne individuelle au sein de cette ressource, celle-ci remplace la culture (thread ou processus) par le resourceCulture spécifié.

Vous pouvez spécifier la langue dans "fr", "de", etc. ou saisir le code de langue dans 0x0409 pour en-US ou 0x0410 pour it-IT. Pour une liste complète des codes de langue, veuillez vous référer à: Identificateurs de langue et paramètres régionaux

17
Reza S

Pour .net 4.5 et supérieur, vous devez utiliser

var culture = new CultureInfo("en-US");
        CultureInfo.DefaultThreadCurrentCulture = culture;
        CultureInfo.DefaultThreadCurrentUICulture = culture;
7
Andreas

En fait, vous pouvez définir la culture de thread et la culture d'interface utilisateur par défaut, mais uniquement avec Framework 4.5+.

Je mets dans ce constructeur statique

static MainWindow()
{
  CultureInfo culture = CultureInfo
    .CreateSpecificCulture(CultureInfo.CurrentCulture.Name);
  var dtf = culture.DateTimeFormat;
  dtf.ShortTimePattern = (string)Microsoft.Win32.Registry.GetValue(
    "HKEY_CURRENT_USER\\Control Panel\\International", "sShortTime", "hh:mm tt");
  CultureInfo.DefaultThreadCurrentUICulture = culture;
}

et mettez un point d'arrêt dans la méthode Convert d'un ValueConverter pour voir ce qui est arrivé à l'autre bout. CultureInfo.CurrentUICulture a cessé d'être en-US et est devenu en-AU complet avec mon petit bidouillage pour lui faire respecter les paramètres régionaux de ShortTimePattern.

Hourra, tout va bien dans le monde! Ou pas. Le paramètre de culture transmis à la méthode Convert est toujours en-US. Euh, WTF?! Mais c'est un début. Au moins de cette façon

  • vous pouvez réparer la culture de l'interface utilisateur une fois au chargement de votre application
  • il est toujours accessible à partir de CultureInfo.CurrentUICulture
  • string.Format("{0}", DateTime.Now) utilisera vos paramètres régionaux personnalisés

Si vous ne pouvez pas utiliser la version 4.5 du framework, renoncez à définir CurrentUICulture en tant que propriété statique de CultureInfo et définissez-la en tant que propriété statique de l'une de vos propres classes. Cela ne résoudra pas le comportement par défaut de string.Format ou ne permettra pas à StringFormat de fonctionner correctement dans les liaisons, puis parcourra l'arborescence logique de votre application pour recréer toutes les liaisons dans votre application et définir leur culture de conversion.

5
Peter Wone

Cette réponse est un peu d’expansion pour la bonne réponse de @ rastating. Vous pouvez utiliser le code suivant pour toutes les versions de .NET sans soucis:

    public static void SetDefaultCulture(CultureInfo culture)
    {
        Type type = typeof (CultureInfo);
        try
        {
            // Class "ReflectionContext" exists from .NET 4.5 onwards.
            if (Type.GetType("System.Reflection.ReflectionContext", false) != null)
            {
                type.GetProperty("DefaultThreadCurrentCulture")
                    .SetValue(System.Threading.Thread.CurrentThread.CurrentCulture,
                        culture, null);

                type.GetProperty("DefaultThreadCurrentUICulture")
                    .SetValue(System.Threading.Thread.CurrentThread.CurrentCulture,
                        culture, null);
            }
            else //.NET 4 and lower
            {
                type.InvokeMember("s_userDefaultCulture",
                    BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
                    null,
                    culture,
                    new object[] {culture});

                type.InvokeMember("s_userDefaultUICulture",
                    BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
                    null,
                    culture,
                    new object[] {culture});

                type.InvokeMember("m_userDefaultCulture",
                    BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
                    null,
                    culture,
                    new object[] {culture});

                type.InvokeMember("m_userDefaultUICulture",
                    BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
                    null,
                    culture,
                    new object[] {culture});
            }
        }
        catch
        {
            // ignored
        }
    }
}
3
polfosol ఠ_ఠ

DefaultThreadCurrentCulture et DefaultThreadCurrentUICulture sont également présents dans Framework 4.0, mais ils sont privés. En utilisant la réflexion, vous pouvez facilement les définir. Cela affectera tous les threads où CurrentCulture n'est pas explicitement défini (les threads en cours d'exécution également).

Public Sub SetDefaultThreadCurrentCulture(paCulture As CultureInfo)
    Thread.CurrentThread.CurrentCulture.GetType().GetProperty("DefaultThreadCurrentCulture").SetValue(Thread.CurrentThread.CurrentCulture, paCulture, Nothing)
    Thread.CurrentThread.CurrentCulture.GetType().GetProperty("DefaultThreadCurrentUICulture").SetValue(Thread.CurrentThread.CurrentCulture, paCulture, Nothing)
End Sub
3
HCAxel

Pour ASP.NET5, c’est-à-dire ASPNETCORE, vous pouvez effectuer les opérations suivantes dans configure:

app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture(new CultureInfo("en-gb")),
    SupportedCultures = new List<CultureInfo>
    {
        new CultureInfo("en-gb")
    },
            SupportedUICultures = new List<CultureInfo>
    {
        new CultureInfo("en-gb")
    }
});

Voici une série d'articles de blog qui donne plus d'informations.

3
Sean

Voici la solution pour c # MVC:

  1. Premièrement: Créez un attribut personnalisé et remplacez la méthode comme ceci:

    public class CultureAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // Retreive culture from GET
            string currentCulture = filterContext.HttpContext.Request.QueryString["culture"];
    
            // Also, you can retreive culture from Cookie like this :
            //string currentCulture = filterContext.HttpContext.Request.Cookies["cookie"].Value;
    
            // Set culture
            Thread.CurrentThread.CurrentCulture = new CultureInfo(currentCulture);
            Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(currentCulture);
        }
    }
    
  2. Deuxièmement: dans App_Start, recherchez FilterConfig.cs, ajoutez cet attribut. (cela fonctionne pour toute l'application)

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            // Add custom attribute here
            filters.Add(new CultureAttribute());
        }
    }    
    

C'est ça !

Si vous souhaitez définir la culture pour chaque contrôleur/action au lieu d'une application entière, vous pouvez utiliser cet attribut comme suit:

[Culture]
public class StudentsController : Controller
{
}

Ou:

[Culture]
public ActionResult Index()
{
    return View();
}
2
Meng Xue