c# - libreria - ¿Hay alguna manera de establecer cultura para una aplicación completa? ¿Todos los hilos actuales y nuevos hilos?
set cultureinfo c# (9)
¿Hay alguna manera de establecer cultura para una aplicación completa? ¿Todos los hilos actuales y nuevos hilos?
Tenemos el nombre de la cultura almacenada en una base de datos, y cuando comienza nuestra aplicación, lo hacemos
CultureInfo ci = new CultureInfo(theCultureString);
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
Pero, por supuesto, esto se "pierde" cuando queremos hacer algo en un nuevo hilo. ¿Hay alguna manera de configurar esa CurrentCulture
y CurrentUICulture
para toda la aplicación? Entonces, ¿qué nuevos hilos también tienen esa cultura? ¿O se dispara algún evento cada vez que se crea un nuevo hilo que me permite conectarme?
Aquí está la solución para c # MVC:
Primero: cree un atributo personalizado y anule el método de esta manera:
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); } }
Segundo: en App_Start, encuentre FilterConfig.cs, agregue este atributo. (Esto funciona para TODA la aplicación)
public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { // Add custom attribute here filters.Add(new CultureAttribute()); } }
Eso es !
Si desea definir la cultura para cada controlador / acción en lugar de toda la aplicación, puede usar este atributo como este:
[Culture]
public class StudentsController : Controller
{
}
O:
[Culture]
public ActionResult Index()
{
return View();
}
De hecho, puede establecer la cultura de la hebra predeterminada y la cultura de la IU, pero solo con Framework 4.5+
Puse en este constructor estático
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;
}
y poner un punto de interrupción en el método Convert de un ValueConverter para ver qué llegó al otro extremo. CultureInfo.CurrentUICulture dejó de ser en-US y pasó a ser en-AU completo con mi pequeño hack para que respete la configuración regional de ShortTimePattern.
¡Hurra, todo está bien en el mundo! O no. El parámetro de cultivo pasado al método Convert todavía está en-US. Erm, WTF ?! Pero es un comienzo. Al menos de esta manera
- puedes arreglar la cultura de la interfaz de usuario una vez cuando se carga tu aplicación
- siempre es accesible desde
CultureInfo.CurrentUICulture
-
string.Format("{0}", DateTime.Now)
usará su configuración regional personalizada
Si no puede usar la versión 4.5 del framework, abandone la configuración de CurrentUICulture como una propiedad estática de CultureInfo y configúrelo como una propiedad estática de una de sus propias clases. Esto no solucionará el comportamiento predeterminado de la cadena. Formatee o haga que StringFormat funcione correctamente en los enlaces, luego recorra el árbol lógico de la aplicación para recrear todos los enlaces en su aplicación y establecer su cultura de conversión.
DefaultThreadCurrentCulture y DefaultThreadCurrentUICulture también están presentes en Framework 4.0, pero son privados. Usando Reflection puedes establecerlos fácilmente. Afecta a todos los threds donde CurrentCulture no está explícitamente configurado (también ejecuta hilos).
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
En .NET 4.5, puede usar la propiedad CultureInfo.DefaultThreadCurrentCulture
para cambiar la cultura de un AppDomain.
Para las versiones anteriores a 4.5, debe usar la reflexión para manipular la cultura de un Dominio de aplicación. Hay un campo estático privado en CultureInfo
( m_userDefaultCulture
en .NET 2.0 mscorlib, s_userDefaultCulture
en .NET 4.0 mscorlib) que controla lo que CurrentCulture
devuelve si un hilo no ha establecido esa propiedad en sí mismo.
Esto no cambia la configuración regional del subproceso nativo y probablemente no sea una buena idea enviar un código que cambie la cultura de esta manera. Sin embargo, puede ser útil para probar.
Esta respuesta es un poco de expansión para la gran respuesta de @rastating. Puede usar el siguiente código para todas las versiones de .NET sin ninguna preocupación:
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
}
}
}
Esto se pregunta mucho. Básicamente, no, no, no es para .NET 4.0. Tienes que hacerlo manualmente al comienzo de cada nuevo hilo (o función ThreadPool
). Tal vez podría almacenar el nombre de la cultura (o simplemente el objeto de cultivo) en un campo estático para evitar tener que presionar la base de datos, pero eso es todo.
Para .net 4.5 y superior, debe usar
var culture = new CultureInfo("en-US");
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;
Para ASP.NET5, es decir, ASPNETCORE, puede hacer lo siguiente en la 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")
}
});
Aquí hay una serie de publicaciones de blog que brinda más información.
Si está utilizando recursos, puede forzarlo manualmente de la siguiente manera:
Resource1.Culture = new System.Globalization.CultureInfo("fr");
En el administrador de recursos, hay un código generado automáticamente que es el siguiente:
/// <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;
}
}
Ahora, cada vez que se refiera a su cadena individual dentro de este recurso, anula la cultura (thread o process) con el resourceCulture especificado.
Puede especificar el idioma como "fr", "de" etc. o poner el código de idioma como en 0x0409 para en-US o 0x0410 para it-IT. Para obtener una lista completa de códigos de idioma, consulte: Identificadores de idioma y configuraciones regionales