¿Hay alguna manera de establecer la cultura para una aplicación completa? Todos los hilos actuales y nuevos hilos?

StackOverflow https://stackoverflow.com/questions/468791

  •  19-08-2019
  •  | 
  •  

Pregunta

¿Hay alguna forma de establecer la 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 se inicia 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 forma de configurar CurrentCulture y CurrentUICulture para toda la aplicación? ¿Entonces esos nuevos hilos también adquieren esa cultura? ¿O se produce algún evento cada vez que se crea un nuevo hilo al que puedo conectarme?

¿Fue útil?

Solución

En .NET 4.5, puede usar el < code> CultureInfo.DefaultThreadCurrentCulture propiedad para cambiar la cultura de un AppDomain.

Para versiones anteriores a la 4.5, debe usar la reflexión para manipular la cultura de un AppDomain. Hay un campo estático privado en CultureInfo ( m_userDefaultCulture en .NET 2.0 mscorlib, s_userDefaultCulture en .NET 4.0 mscorlib) que controla qué CurrentCulture regresa si un hilo no ha establecido esa propiedad en sí mismo.

Esto no cambia la configuración nativa del hilo y probablemente no sea una buena idea enviar código que cambie la cultura de esta manera. Sin embargo, puede ser útil para realizar pruebas.

Otros consejos

Esto se pregunta mucho. Básicamente, no, no hay, no para .NET 4.0. Debe hacerlo manualmente al comienzo de cada nuevo hilo (o función ThreadPool ). Tal vez podría almacenar el nombre de la cultura (o solo el objeto de la cultura) en un campo estático para evitar tener que presionar la base de datos, pero eso es todo.

Si está utilizando recursos, puede forzarlo manualmente:

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 hace referencia a su cadena individual dentro de este recurso, anula la cultura (hilo o proceso) con la ResourceCulture especificada.

Puede especificar el idioma como en '' fr '', '' de '' etc. o coloque 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

Para .net 4.5 y superior, debe usar

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

En realidad, usted puede establecer la cultura de subprocesos 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 coloque 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 se convirtió en en-AU completo con mi pequeño truco para que respete la configuración regional de ShortTimePattern.

¡Hurra, todo está bien en el mundo! O no. El parámetro de cultura pasado al método Convert es still 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 marco, deje de configurar 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 string.Format o hará que StringFormat funcione correctamente en enlaces, luego recorra el árbol lógico de su aplicación para recrear todos los enlaces en su aplicación y establecer su cultura de conversión.

Para ASP.NET5, es decir, ASPNETCORE, puede hacer lo siguiente en 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.

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 preocupaciones:

    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 y DefaultThreadCurrentUICulture también están presentes en Framework 4.0, pero son privados. Usando Reflection puedes configurarlos fácilmente. Esto afectará a todos los hilos donde CurrentCulture no está establecido explícitamente (ejecutando hilos también).

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

Aquí está la solución para c # MVC:

  1. Primero: cree un atributo personalizado y anule un método como este:

    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. Segundo: en App_Start, busque 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 la aplicación completa, puede usar este atributo de esta manera:

[Culture]
public class StudentsController : Controller
{
}

O:

[Culture]
public ActionResult Index()
{
    return View();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top