有没有办法为整个应用程序设置文化?所有当前线程和新线程?
我们将文化的名称存储在数据库中,当我们的应用程序启动时,我们会
CultureInfo ci = new CultureInfo(theCultureString);
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
但是,当然,当我们想要在新线程中做某事时,这会“丢失”。有没有办法为整个应用程序设置CurrentCulture
和CurrentUICulture
?那么新线程也会获得这种文化?或者,只要创建了一个我可以连接的新线程,就会触发某个事件?
答案 0 :(得分:185)
在.NET 4.5中,您可以使用CultureInfo.DefaultThreadCurrentCulture
属性来更改AppDomain的文化。
对于4.5之前的版本,您必须使用反射来操纵AppDomain的文化。 CultureInfo
上的私有静态字段(.NET 2.0 mscorlib中为m_userDefaultCulture
,.NET 4.0 mscorlib中为s_userDefaultCulture
),如果线程未设置,则控制CurrentCulture
返回的内容这个属性本身。
这不会更改本机线程区域设置,并且发布以这种方式更改文化的代码可能不是一个好主意。但它可能对测试很有用。
答案 1 :(得分:35)
这被问了很多。基本上,没有,不适用于.NET 4.0。您必须在每个新线程(或ThreadPool
函数)的开头手动执行此操作。您可以将文化名称(或文化对象)存储在静态字段中以节省必须访问数据库,但这就是它。
答案 2 :(得分: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”,“de”等语言,也可以将语言代码设置为en-US的0x0409或it-IT的0x0410。有关语言代码的完整列表,请参阅:Language Identifiers and Locales
答案 3 :(得分:7)
对于.net 4.5及更高版本,您应该使用
var culture = new CultureInfo("en-US");
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;
答案 4 :(得分:5)
实际上你可以设置默认的线程文化和UI文化,但只能使用Framework 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的Convert方法中放置一个断点,以查看到达另一端的内容。 CultureInfo.CurrentUICulture不再是en-US,而是通过我的小黑客完成en-AU,使其尊重ShortTimePattern的区域设置。
华友世纪,世界上一切都很好!或不。传递给Convert方法的culture参数是仍然 en-US。呃,WTF?!但这是一个开始。至少这样
CultureInfo.CurrentUICulture
string.Format("{0}", DateTime.Now)
将使用您自定义的区域设置如果你不能使用框架的4.5版,那么就放弃将CurrentUICulture设置为CultureInfo的静态属性,并将其设置为你自己的一个类的静态属性。这不会修复string.Format的默认行为或使StringFormat在绑定中正常工作,然后遍历应用程序的逻辑树以重新创建应用程序中的所有绑定并设置其转换器文化。
答案 5 :(得分:3)
DefaultThreadCurrentCulture
和DefaultThreadCurrentUICulture
,但它们是私有的。使用Reflection您可以轻松设置它们。这将影响未明确设置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
答案 6 :(得分: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。
答案 7 :(得分: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
}
}
}
答案 8 :(得分:2)
以下是c#MVC的解决方案:
首先:创建一个自定义属性并覆盖如下方法:
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());
}
}
就是这样!
如果要为每个控制器/操作定义文化而不是整个应用程序,可以使用以下属性:
[Culture]
public class StudentsController : Controller
{
}
或者:
[Culture]
public ActionResult Index()
{
return View();
}
答案 9 :(得分:1)
为所有线程和窗口设置CultureInfo的有效解决方案。
<Application ........
Startup="Application_Startup"
>
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;
}
}