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
Is there a way of setting culture for a whole application? All current threads and new threads?
提问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 CurrentCulture
and CurrentUICulture
for 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.DefaultThreadCurrentCulture
property 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_userDefaultCulture
in .NET 2.0 mscorlib, s_userDefaultCulture
in .NET 4.0 mscorlib) that controls what CurrentCulture
returns if a thread has not set that property on itself.
对于 4.5 之前的版本,您必须使用反射来操纵 AppDomain 的文化。CultureInfo
(m_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 ThreadPool
function). 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
DefaultThreadCurrentCulture
and DefaultThreadCurrentUICulture
are present in Framework 4.0 too, but they are Private. Using Reflection you can easily set them. This will affect all threads where CurrentCulture
is 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 的解决方案:
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); } }
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()); } }
首先:创建一个自定义属性并覆盖方法,如下所示:
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); } }
第二:在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 的工作解决方案。
- Open App.xamlfile and add a new "Startup" attribute to assign startup event handler for the app:
- 打开App.xaml文件并添加一个新的“启动”属性来为应用程序分配启动事件处理程序:
<Application ........
Startup="Application_Startup"
>
- Open App.xaml.csfile and add this code to created startup handler (Application_Startup in this case). The class App will look like this:
- 打开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;
}
}