web-dev-qa-db-ja.com

アプリケーション全体に文化を設定する方法はありますか?すべての現在のスレッドと新しいスレッド?

アプリケーション全体にカルチャを設定する方法はありますか?現在のすべてのスレッドと新しいスレッド?

カルチャの名前はデータベースに保存されており、アプリケーションの起動時に

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

しかし、もちろん、新しいスレッドで何かをしたいとき、これは「失われます」。アプリケーション全体に対してCurrentCultureおよびCurrentUICultureを設定する方法はありますか?それで、新しいスレッドもその文化を取得しますか?または、フックできる新しいスレッドが作成されるたびに発生するイベントですか?

171
Svish

.NET 4.5では、 CultureInfo.DefaultThreadCurrentCulture プロパティを使用してAppDomainのカルチャを変更できます。

4.5より前のバージョンでは、リフレクションを使用してAppDomainのカルチャを操作する必要があります。 CultureInfo(.NET 2.0 mscorlibのm_userDefaultCulture 、. NET 4.0 mscorlibのs_userDefaultCulture)には、静的プロパティがあり、スレッドがそのプロパティを設定していない場合にCurrentCultureが返すものを制御します。

これは、ネイティブスレッドのロケールを変更するものではありません。おそらく、この方法でカルチャを変更するコードを出荷することはお勧めできません。ただし、テストには役立ちます。

189
Austin

これはよく聞かれます。基本的にはありません。NET4.0ではありません。新しいスレッド(またはThreadPool関数)の開始時に手動で行う必要があります。おそらく、カルチャ名(またはカルチャオブジェクトのみ)を静的フィールドに格納して、DBにアクセスする手間を省くことができますが、それだけです。

36
Marc Gravell

リソースを使用している場合、次の方法で手動で強制できます。

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のように言語コードを入力できます。言語コードの完全なリストについては、以下を参照してください。 言語識別子とロケール

17
Reza S

.net 4.5以降では、使用する必要があります

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

実際にはcanデフォルトのスレッドカルチャと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メソッドに渡されるカルチャパラメータはstill en-USです。うーん、WTF ?!しかし、それは始まりです。少なくともこのように

  • アプリの読み込み時にUIカルチャを一度修正できます
  • CultureInfo.CurrentUICultureから常にアクセス可能です
  • string.Format("{0}", DateTime.Now)は、カスタマイズされた地域設定を使用します

フレームワークのバージョン4.5を使用できない場合は、CurrentUICultureをCultureInfoの静的プロパティとして設定することをあきらめ、独自のクラスの1つの静的プロパティとして設定します。これは、string.Formatのデフォルトの動作を修正したり、バインディングでStringFormatを適切に動作させたりしてから、アプリの論理ツリーをたどってアプリ内のすべてのバインディングを再作成し、コンバーターカルチャを設定します。

5
Peter Wone

この答えは、@ 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

DefaultThreadCurrentCultureおよびDefaultThreadCurrentUICultureもFramework 4.0に存在しますが、プライベートです。 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
3
HCAxel

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

一連のブログ投稿 は、より多くの情報を提供します。

3
Sean

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. 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();
}
2
Meng Xue