C# 有没有办法为整个应用程序设置文化?所有当前线程和新线程?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/468791/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 04:37:04  来源:igfitidea点击:

Is there a way of setting culture for a whole application? All current threads and new threads?

c#multithreadingcultureinfo

提问by Svish

Is there a way of setting culture for a whole application? All current threads and new threads?

有没有办法为整个应用程序设置文化?所有当前线程和新线程?

We have the name of the culture stored in a database, and when our application starts, we do

我们将文化的名称存储在数据库中,当我们的应用程序启动时,我们执行

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

But, of course, this gets "lost" when we want to do something in a new thread. Is there a way of setting that CurrentCultureand CurrentUICulturefor the whole application? So that new threads also gets that culture? Or is it some event fired whenever a new thread is created that I can hook up to?

但是,当然,当我们想在新线程中做某事时,这会“丢失”。是否有设置,的一种方式CurrentCulture,并CurrentUICulture为整个应用程序?那么新线程也获得了这种文化?还是每当创建一个我可以连接的新线程时都会触发某个事件?

采纳答案by Austin

In .NET 4.5, you can use the CultureInfo.DefaultThreadCurrentCultureproperty to change the culture of an AppDomain.

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

For versions prior to 4.5 you have to use reflection to manipulate the culture of an AppDomain. There is a private static field on CultureInfo(m_userDefaultCulturein .NET 2.0 mscorlib, s_userDefaultCulturein .NET 4.0 mscorlib) that controls what CurrentCulturereturns if a thread has not set that property on itself.

对于 4.5 之前的版本,您必须使用反射来操纵 AppDomain 的文化。CultureInfom_userDefaultCulture在 .NET 2.0 mscorlib 中,s_userDefaultCulture在 .NET 4.0 mscorlib 中)上有一个私有静态字段,它控制CurrentCulture如果线程没有为其自身设置该属性则返回的内容。

This does not change the native thread locale and it is probably not a good idea to ship code that changes the culture this way. It may be useful for testing though.

这不会更改本机线程区域设置,并且以这种方式发布更改文化的代码可能不是一个好主意。不过,它可能对测试有用。

回答by Marc Gravell

This gets asked a lot. Basically, no there isn't, not for .NET 4.0. You have to do it manually at the start of each new thread (or ThreadPoolfunction). You could perhaps store the culture name (or just the culture object) in a static field to save having to hit the DB, but that's about it.

这被问了很多。基本上,没有没有,不适用于 .NET 4.0。您必须在每个新线程(或ThreadPool函数)开始时手动执行此操作。您也许可以将文化名称(或仅文化对象)存储在静态字段中,以节省访问数据库的时间,但仅此而已。

回答by Reza S

If you are using resources, you can manually force it by:

如果您正在使用资源,您可以通过以下方式手动强制使用:

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

In the resource manager, there is an auto generated code that is as follows:

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

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

Now every time you refer to your individual string within this resource, it overrides the culture (thread or process) with the specified resourceCulture.

现在,每次您在此资源中引用您的单个字符串时,它都会使用指定的资源文化覆盖区域性(线程或进程)。

You can either specify language as in "fr", "de" etc. or put the language code as in 0x0409 for en-US or 0x0410 for it-IT. For a full list of language codes please refer to: Language Identifiers and Locales

您可以将语言指定为“fr”、“de”等,也可以将语言代码置于 0x0409(表示 en-US)或 0x0410(表示 it-IT)。有关语言代码的完整列表,请参阅:语言标识符和区域设置

回答by Peter Wone

Actually you canset the default thread culture and UI culture, but only with Framework 4.5+

实际上你可以设置默认的线程文化和 UI 文化,但仅限于 Framework 4.5+

I put in this static constructor

我放入了这个静态构造函数

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

and put a breakpoint in the Convert method of a ValueConverter to see what arrived at the other end. CultureInfo.CurrentUICulture ceased to be en-US and became instead en-AU complete with my little hack to make it respect regional settings for ShortTimePattern.

并在 ValueConverter 的 Convert 方法中放置一个断点,以查看到达另一端的内容。CultureInfo.CurrentUICulture 不再是 en-US,而是通过我的小技巧变成了 en-AU,以使其尊重 ShortTimePattern 的区域设置。

Hurrah, all is well in the world! Or not. The culture parameter passed to the Convert method is stillen-US. Erm, WTF?! But it's a start. At least this way

万岁,世间万事如意!或不。传递给 Convert 方法的文化参数仍然是en-US。嗯,WTF?!但这是一个开始。至少这样

  • you can fix the UI culture once when your app loads
  • it's always accessible from CultureInfo.CurrentUICulture
  • string.Format("{0}", DateTime.Now)will use your customised regional settings
  • 您可以在应用加载时修复一次 UI 文化
  • 它总是可以从 CultureInfo.CurrentUICulture
  • string.Format("{0}", DateTime.Now)将使用您自定义的区域设置

If you can't use version 4.5 of the framework then give up on setting CurrentUICulture as a static property of CultureInfo and set it as a static property of one of your own classes. This won't fix default behaviour of string.Format or make StringFormat work properly in bindings then walk your app's logical tree to recreate all the bindings in your app and set their converter culture.

如果您不能使用框架的 4.5 版,则放弃将 CurrentUICulture 设置为 CultureInfo 的静态属性并将其设置为您自己的类之一的静态属性。这不会修复 string.Format 的默认行为或使 StringFormat 在绑定中正常工作,然后遍历应用程序的逻辑树以重新创建应用程序中的所有绑定并设置它们的转换器文化。

回答by HCAxel

DefaultThreadCurrentCultureand DefaultThreadCurrentUICultureare present in Framework 4.0 too, but they are Private. Using Reflection you can easily set them. This will affect all threads where CurrentCultureis not explicitly set (running threads too).

DefaultThreadCurrentCulture并且DefaultThreadCurrentUICulture也存在于 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

回答by Sean

For ASP.NET5, i.e. ASPNETCORE, you can do the following in configure:

对于 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")
    }
});

Here's a series of blog poststhat gives more information.

这是提供更多信息的一系列博客文章

回答by Meng Xue

Here is the solution for c# MVC:

这是 c# MVC 的解决方案:

  1. First : Create a custom attribute and override method like this:

    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. Second : In App_Start, find FilterConfig.cs, add this attribute. (this works for WHOLE application)

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            // Add custom attribute here
            filters.Add(new CultureAttribute());
        }
    }    
    
  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());
        }
    }    
    

That's it !

就是这样 !

If you want to define culture for each controller/action in stead of whole application, you can use this attribute like this:

如果你想为每个控制器/动作而不是整个应用程序定义文化,你可以像这样使用这个属性:

[Culture]
public class StudentsController : Controller
{
}

Or:

或者:

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

回答by Andreas

For .net 4.5 and higher you should use

对于 .net 4.5 及更高版本,您应该使用

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

回答by polfosol ?_?

This answer is a bit of expansion for @rastating's great answer. You can use the following code for all versions of .NET without any worries:

这个答案是@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
        }
    }
}

回答by Rustam Shafigullin

Working solution to set CultureInfo for all threads and windows.

为所有线程和窗口设置 CultureInfo 的工作解决方案。

  1. Open App.xamlfile and add a new "Startup" attribute to assign startup event handler for the app:
  1. 打开App.xaml文件并添加一个新的“启动”属性来为应用程序分配启动事件处理程序:
<Application ........
             Startup="Application_Startup"
>
  1. Open App.xaml.csfile and add this code to created startup handler (Application_Startup in this case). The class App will look like this:
  1. 打开App.xaml.cs文件并将此代码添加到创建的启动处理程序(在本例中为 Application_Startup)。类 App 将如下所示:
    public partial class App : Application
    {
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            CultureInfo cultureInfo = CultureInfo.GetCultureInfo("en-US");
            System.Globalization.CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
            System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
            Thread.CurrentThread.CurrentCulture = cultureInfo;
        }
    }