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


177

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

データベースに保存されているカルチャの名前があり、アプリケーションが起動すると、

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

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


4
リソースを使用している場合は、次の方法で手動で強制できます。Resource1.Culture = new System.Globalization.CultureInfo( "fr"); このようにして、文字列を取得するたびに、ローカライズされて返されます
Reza S

回答:


196

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

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

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


9
ASP.NETアプリケーションでは、この設定に注意してください。AppDomainにカルチャを設定すると、すべてのユーザーのカルチャが設定されます。したがって、たとえば英語のユーザーがドイツ語でWebサイトを表示するのは良くありません。
Dimitar Tsonev 2015年

2
すべてのカルチャがen-USにある場合にのみ機能するASP.NETアプリケーションを継承しました。これは、この問題が修正されるまでの間、この設定が最適であるシナリオです
Daniel Hilgarth

37

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


1
ちょっと迷惑な...あなたは正しいようです、へへ。したがって、今はそれを行います(そしてカルチャに静的クラスを設定します)が、制御できないいくつかのスレッドにまだ問題があります。Microsoftレポートビューアーでスレッドを処理するようなものです。しかし、回避策を見つけました。情報ありがとうございました:)
Svish

8
これは本当に迷惑です:(アプリケーションに自動的に現在の(UI)の文化を設定し、すべての新しいスレッドがその値を拾う持つ方法があった場合、それはいいだろう。
Jedidja

1
私がこれを使って作業するようになって久しいので、私たちが何をしたか正確には覚えていません。しかし、レポートビューアーに送信されたデータセットの日付を使用する代わりに、アプリケーションで設定したカルチャを使用して、最初に日付を文字列にフォーマットした可能性があります。その後、レポートレンダリングスレッドが間違ったカルチャを使用することは、もはや問題ではなくなりました。したがって、間違ったカルチャを使用するスレッドの問題を回避しませんでした。日付の形式が正しくないという問題を回避しました:)
Svish

2
私たちのアプリでは、(特定の場所から特別なメソッドを呼び出して)スレッドを「キャプチャ」し、後で使用するために(この場合はカルチャを設定するために)スレッドをコレクションに格納しようとしましたが、これはかなり機能しているようです。
TA氏

1
セッションにcultureinfoオブジェクトを格納し、(マスターページを使用している場合)マスターページのコードビハインドでそれを確認し、現在のスレッドを設定できませんか?
user609926

20

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

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


:それはヌルに設定することで、「自発的」することができResource1.Culture = Null;
Habakukの

8

.net 4.5以降の場合は、

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

6

実際にできます、デフォルトのスレッドカルチャと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の静的プロパティとして設定することをあきらめ、独自のクラスの1つの静的プロパティとして設定します。これは、string.Formatのデフォルトの動作を修正しないか、バインディングでStringFormatを適切に機能させてから、アプリの論理ツリーをウォークしてアプリ内のすべてのバインディングを再作成し、それらのコンバーターカルチャを設定します。


1
オースティンの回答は、CultureInfo.DefaultThreadCurrentCultureを設定してAppDomainのカルチャを変更できるという洞察をすでに提供しています。CultureInfo.DefaultThreadCurrentUICultureはCurrentUICultureに対するもので、CultureInfo.DefaultThreadCurrentCultureはCurrentCultureに対するものです。コードのレジストリから直接値を取得する理由は本当にありません。CurrentCultureを特定のカルチャに変更したいが、ユーザーオーバーライドを保持したい場合は、オーバーライドする前にCurrentCultureのDateTimeFormatから値を取得する必要があります。
Eric MSFT 2014年

1
私はチェックする必要がありますが、成功せずにそれを試すことを覚えているようで、レジストリから取得することにつながります。私がそのようなトラブルに何の理由もなく行くと本当に思いますか?レジストリアクセスは、UACのこの勇敢な新しい世界における巨大なPITAです。
Peter Wone 2014年

4

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

これは、より多くの情報を提供する一連のブログ投稿です。


1
レガシーASP.NET 2.0サイトでこれを行う方法を探していましたが、別のコアサイトで比較して管理するのがいかに簡単かイライラします。私は多国籍企業に所属しており、内部サイトの場合、日付の混乱を防ぐためにすべてのフォーマットはen-​​USです。ただし、このレガシーサイトはen-​​US、en-CA、fr-CA用に設定されています。そして「ハック」な方法で、それを修正しようとすると、すべての型変換がデータレイヤーで爆破します。(フランスの通貨の値は "1 234,56 $"
Andrew S

1
@Seanリンクが壊れています。多分それはこれこれこれを
Fer R

4

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

4

DefaultThreadCurrentCultureそしてDefaultThreadCurrentUICulture、あまりにもフレームワーク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

1
これは私のために働いた。Thread.CurrentThread.CurrentCulture = Cultureを使用していますが、Thread.CurrentThread.CurrentUICulture =文化; 同じように見えませんでした。明確にするために、これはWPFアプリで使用されており、アプリ自体がカルチャを変更していましたが、他のプロジェクトのユーザー
コントロール

3

これは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を見つけ、この属性を追加します。(これはWHOLEアプリケーションで機能します)

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

1

すべてのスレッドとウィンドウにCultureInfoを設定するための実用的なソリューション。

  1. App.xamlファイルを開き、新しい "Startup"属性を追加して、アプリの起動イベントハンドラーを割り当てます。
<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;
        }
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.