是否有一个整体的应用程序设置文化的一种方式?目前所有的线程和新主题?

问题描述 投票:167回答:9

是否有一个整体的应用程序设置文化的一种方式?目前所有的线程和新主题?

我们有存储在数据库中文化的名字,和我们的应用程序启动时,我们做

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

但是,当然,这个被“丢失”当我们想要做的东西在一个新的线程。是否有设置,CurrentCultureCurrentUICulture整个应用程序的方法吗?这样新主题也得到这种文化?或者是一些事件,每当一个新的线程被创建,我可以钩到解雇?

c# multithreading cultureinfo
9个回答
189
投票

在.NET 4.5中,您可以使用CultureInfo.DefaultThreadCurrentCulture属性来更改一个AppDomain的文化。

对于之前的4.5版本中,你必须使用反射来操纵一个AppDomain的文化。有上CultureInfo私有静态字段(m_userDefaultCulture在.NET 2.0的mscorlib,s_userDefaultCulture在.NET 4.0的mscorlib)控制,如果一个线程没有设置本身属性是什么CurrentCulture返回。

这不会改变本地线程区域,它可能不是出货的代码,改变了文化的这样一个好主意。这可能是用于测试,但。


36
投票

这个被问了很多。基本上,没有没有,不是.NET 4.0。你必须在每一个新的线程(或ThreadPool功能)开始做手工。也许你可以在一个静态字段文化名(或只是培养对象)存储,省去打DB,但仅此而已。


17
投票

如果您使用的资源,您可以手动迫使它通过:

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

在资源管理器中,有一个自动生成的代码如下:

/// <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;
    }
}

现在,每次你参考您的个人的字符串在此资源内时,它会覆盖文化(线程或进程)使用指定resourceCulture。

您可以指定语言为“FR”,“德”等,或把语言代码为0x0409为EN-US或阿拉伯语 - 约旦它-IT。有关语言代码的完整列表,请参阅:Language Identifiers and Locales


7
投票

对于.NET 4.5和更高的你应该使用

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

5
投票

其实你可以设置默认的线程文化和UI文化,但只有框架4.5+

我把这个静态构造函数

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;
}

将断点设置在ValueConverter的转换方法,看看在另一端是什么来了。 CultureInfo.CurrentUICulture不再是EN-美国,成为代替EN-AU完成我的小黑客,使之尊重区域设置ShortTimePattern。

华友世纪,一切都很好,在世界上!或不。传递给转换方法的文化参数仍然是EN-US。呃,WTF?但它是一个开始。至少这样

  • 你可以在你的应用程序加载修复UI区域性一次
  • 它总是从CultureInfo.CurrentUICulture访问
  • string.Format("{0}", DateTime.Now)将使用您的自定义区域设置

如果您无法使用该框架的4.5版本,那么放弃对设置的CurrentUICulture作为CultureInfo的静态属性并将其设置为自己的一个类的静态属性。这不会解决的String.format的默认行为或使绑定的StringFormat正常工作,然后走你的应用程序的逻辑树重新创建你的应用程序中的所有绑定,并设置其转换的文化。


3
投票

对于ASP.NET5,即ASPNETCORE,你可以做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")
    }
});

下面是提供了更多的信息series of blog posts


3
投票

这个答案是有点扩张@ rastating最伟大的答案。您可以使用.NET的所有版本的下面的代码没有任何后顾之忧:

    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
投票

DefaultThreadCurrentCultureDefaultThreadCurrentUICulture存在于Framework 4.0中也一样,但它们是私有的。使用反射,你可以轻松地进行设置。这将影响地方CurrentCulture未明确设置的所有线程(正在运行的线程太)。

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

2
投票

下面是C#MVC的解决方案:

  1. 第一:像这样创建一个自定义属性,并重写方法: 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. 第二:在App_Start,发现FilterConfig.cs,添加此属性。 (这适用于整个应用程序) public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { // Add custom attribute here filters.Add(new CultureAttribute()); } }

而已 !

如果你想将文化定义为整个应用程序的每个代替控制器/动作,你可以使用这样该属性:

[Culture]
public class StudentsController : Controller
{
}

要么:

[Culture]
public ActionResult Index()
{
    return View();
}
© www.soinside.com 2019 - 2024. All rights reserved.