[C#] 전체 응용 프로그램의 문화를 설정하는 방법이 있습니까? 모든 현재 스레드와 새 스레드?

전체 응용 프로그램의 문화를 설정하는 방법이 있습니까? 모든 현재 스레드와 새 스레드?

우리는 데이터베이스에 저장된 문화의 이름을 가지고 있으며 응용 프로그램이 시작될 때

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

그러나 물론 새로운 스레드에서 무언가를 원할 때 “손실”됩니다. 것을 설정하는 방법이 CurrentCultureCurrentUICulture전체 응용 프로그램은? 그래서 새로운 스레드도 그 문화를 얻습니까? 아니면 새 스레드를 만들 때마다 연결될 수있는 이벤트가 발생합니까?



답변

.NET 4.5에서는이 CultureInfo.DefaultThreadCurrentCulture속성을 사용하여 AppDomain의 문화권을 변경할 수 있습니다 .

4.5 이전 버전의 경우 리플렉션을 사용하여 AppDomain의 문화를 조작해야합니다. 스레드가 해당 속성을 자체적으로 설정하지 않은 경우 반환되는 내용을 제어 하는 개인 정적 필드 CultureInfo( m_userDefaultCulture.NET 2.0 mscorlib, s_userDefaultCulture.NET 4.0 mscorlib)가 CurrentCulture있습니다.

이것은 기본 스레드 로케일을 변경하지 않으며 문화를 이런 식으로 변경하는 코드를 제공하는 것은 좋지 않습니다. 그래도 테스트에 유용 할 수 있습니다.


답변

이것은 많은 질문을받습니다. 기본적으로 .NET 4.0에는 없습니다. 각각의 새 스레드 (또는 ThreadPool기능) 가 시작될 때 수동으로 수행해야합니다 . 문화권 이름 (또는 문화권 객체)을 정적 필드에 저장하여 DB를 칠 필요가 없도록 할 수는 있지만 그게 전부입니다.


답변

리소스를 사용하는 경우 다음을 통해 수동으로 리소스를 강제 실행할 수 있습니다.

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과 같이 언어 코드를 입력 할 수 있습니다. 언어 코드의 전체 목록은 언어 식별자 및 로캘을 참조하십시오.


답변

.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로 중단되었으며 대신 ShortTimePattern의 지역 설정을 존중하기 위해 작은 핵으로 완성되었습니다.

Hurrah, 세상은 모두 잘 지내고 있습니다! 아님 Convert 메서드에 전달 된 culture 매개 변수는 여전히 en-US입니다. 음, WTF ?! 그러나 시작입니다. 적어도 이런 식으로

  • 앱이로드 될 때 UI 문화를 한 번 수정할 수 있습니다
  • 그것은 항상 접근 할 수 있습니다 CultureInfo.CurrentUICulture
  • string.Format("{0}", DateTime.Now) 맞춤 지역 설정을 사용합니다

버전 4.5의 프레임 워크를 사용할 수 없다면 CurrentUICulture를 CultureInfo의 정적 속성으로 설정하지 말고 자신의 클래스 중 하나의 정적 속성으로 설정하십시오. 이것은 문자열의 기본 동작을 수정하지 않습니다. 바인딩에서 바인딩 또는 StringFormat이 제대로 작동하도록 한 다음 앱의 논리 트리를 따라 이동하여 앱의 모든 바인딩을 다시 만들고 변환기 문화를 설정하십시오.


답변

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