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?
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.
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.
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
Pour .net 4.5 et supérieur, vous devez utiliser
var culture = new CultureInfo("en-US");
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;
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
CultureInfo.CurrentUICulture
string.Format("{0}", DateTime.Now)
utilisera vos paramètres régionaux personnalisésSi 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.
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
}
}
}
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
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.
Voici la solution pour c # MVC:
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);
}
}
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();
}