繁体   English   中英

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

实际上你可以设置默认的线程文化和 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 方法的文化参数仍然是 en-US。 嗯,WTF?! 但这是一个开始。 至少这样

  • 您可以在应用加载时修复一次 UI 文化
  • 它始终可以从CultureInfo.CurrentUICulture访问
  • string.Format("{0}", DateTime.Now)将使用您自定义的区域设置

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

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

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

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

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

这是 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();
}

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

  1. 打开App.xaml文件并添加一个新的“启动”属性来为应用程序分配启动事件处理程序:
<Application ........
             Startup="Application_Startup"
>
  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;
            Thread.CurrentThread.CurrentUICulture = cultureInfo;
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM