Bütün bir uygulama için kültür oluşturmanın bir yolu var mı? Tüm güncel konular ve yeni konular?


177

Bütün bir uygulama için kültür oluşturmanın bir yolu var mı? Tüm güncel konular ve yeni konular?

Veritabanında depolanan kültürün ismine sahibiz ve uygulamamız başladığında

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

Ancak, elbette, yeni bir iş parçacığında bir şeyler yapmak istediğimizde bu "kaybolur". Bunu CurrentCultureve CurrentUICulturetüm uygulama için bir ayar yolu var mı ? Yani yeni iplikler de bu kültüre sahip mi? Yoksa yeni bir iş parçacığı oluşturulduğunda bağlanabileceğim bir olay mı var?


4
Kaynakları kullanıyorsanız, kaynak kodunu manuel olarak zorlayabilirsiniz: Resource1.Culture = new System.Globalization.CultureInfo ("fr"); Bu şekilde, bir dizeyi her almak istediğinizde, yerelleştirilir ve geri döndürülür
Reza S

Yanıtlar:


196

.NET 4.5'te, CultureInfo.DefaultThreadCurrentCulture 4.5'te, bir AppDomain kültürünü değiştirmek için özelliği .

4.5'ten önceki sürümler için, bir AppDomain kültürünü değiştirmek için yansıma kullanmanız gerekir. Üzerinde CultureInfo( m_userDefaultCulture.NET 2.0 mscorlib'de, s_userDefaultCulture.NET 4.0 mscorlib'de) özel bir statik alan vardır.CurrentCultureBir iş parçacığı bu özelliği kendi başına ayarlamamışsa döndürdüğünü .

Bu, yerel iş parçacığı yerel ayarını değiştirmez ve kültürü bu şekilde değiştiren kod göndermek muhtemelen iyi bir fikir değildir. Yine de test için yararlı olabilir.


9
ASP.NET uygulamalarında bu ayara dikkat edin. AppDomain'de kültürün ayarlanması, kültürü tüm kullanıcılar için ayarlar. Bu nedenle, İngilizce kullanıcısının web sitesini Almanca olarak görmesi iyi olmayacaktır.
Dimitar Tsonev

2
Yalnızca tüm kültürler ABD'de ise çalışan bir ASP.NET uygulamasını devralmıştım. Bu, bu ayarın bu kusur giderilene kadar mükemmel olduğu bir senaryodur
Daniel Hilgarth

37

Bu çok sorulur. Temel olarak, .NET 4.0 için değil, hayır. Her yeni iş parçacığının (veya ThreadPoolişlevinin) başında bunu manuel olarak yapmanız gerekir . DB'ye vurmak zorunda kalmamak için kültür adını (veya sadece kültür nesnesini) statik bir alanda saklayabilirsiniz.


1
biraz sinir bozucu ... haklı görünüyorsun hehe. Şimdi bunu yapıyoruz (ve kültüre statik bir sınıfımız var), ama hala üzerinde kontrol sahibi olmadığımız bazı iş parçacıkları ile ilgili bir sorunumuz var. Microsoft rapor görüntüleyicisindeki iş parçacıklarını işlemek gibi. Gerçi bir iş buldum. Bilgi için teşekkür ederim :)
Svish

8
Bu gerçekten sinir bozucu :( Geçerli (UI) Kültürünü uygulamanız için otomatik olarak ayarlamanın ve tüm yeni iş parçacıklarının bu değeri
almasını sağlamanın

1
Şimdi bununla çalıştığımdan beri çok uzun, bu yüzden ne yaptığımızı tam olarak hatırlamıyorum. Ancak, rapor görüntüleyiciye gönderilen veri kümesinde tarihleri ​​kullanmak yerine, uygulamada ayarladığımız kültürü kullanarak tarihi bir dizeye biçimlendirdik. O zaman artık konuları işleyen raporun yanlış kültürü kullanması gerçekten önemli değildi. Bu yüzden yanlış kültürü kullanan iş parçacıkları ile ilgili problemi çözmedik. Tarihlerin yanlış biçimlendirilmesi sorununu
çözdük

2
Bizim app, ben (belirli yerlerden özel bir yöntem çağırarak) konuları "yakalama" denedim ve çok çalışıyor gibi görünüyor daha sonra kullanım için (bu durumda kültür ayarlamak için) bir koleksiyonda saklamak.
Sayın TA

1
Cultureinfo nesnesini oturumda saklayamadınız ve (masterpages kullanıyorsanız) bunu ana sayfa kodunuzda kontrol edip geçerli iş parçacığını ayarlayamadınız mı?
user609926

20

Kaynakları kullanıyorsanız, aşağıdakileri manuel olarak zorlayabilirsiniz:

Resource1.Culture = new System.Globalization.CultureInfo("fr"); 

Kaynak yöneticisinde, otomatik olarak oluşturulan ve aşağıdaki gibi bir kod vardır:

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

Şimdi bu kaynak içindeki bireysel dizenize her başvurduğunuzda, belirtilen resourceCulture ile kültürü (iş parçacığı veya işlem) geçersiz kılar.

Dili "fr", "de" vb. Gibi belirtebilir veya dil kodunu en-US için 0x0409 veya it-IT için 0x0410 olarak girebilirsiniz. Dil kodlarının tam listesi için lütfen bakınız: Dil Tanımlayıcıları ve Yerel Ayarlar


Boş olarak ayarlayarak "zorla" olabilir:Resource1.Culture = Null;
habakuk

8

.Net 4.5 ve sonraki sürümler için

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

6

Aslında yapabilirsiniz ama sadece Çerçevesi ile, varsayılan iplik kültürü ve UI kültürü ayarlamak 4.5+

Bu statik yapıcıya koydum

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

ve diğer uca neyin geldiğini görmek için bir ValueConverter'ın Convert yöntemine bir kesme noktası koyun. CultureInfo.CurrentUICulture en-US olmayı bıraktı ve bunun yerine ShortTimePattern için bölgesel ayarlara saygı duymasını sağlamak için küçük hack'imle en-AU tamamlandı.

Yaşasın, dünyada her şey yolunda! Ya da değil. Convert yöntemine iletilen kültür parametresi hala en-US şeklindedir. Hmm, WTF ?! Ama bu bir başlangıç. En azından bu şekilde

  • uygulamanız yüklendiğinde kullanıcı arayüzü kültürünü bir kez düzeltebilirsiniz
  • her zaman erişilebilir CultureInfo.CurrentUICulture
  • string.Format("{0}", DateTime.Now) özelleştirilmiş bölgesel ayarlarınızı kullanacak

Çerçevenin 4.5 sürümünü kullanamıyorsanız, CurrentUICulture'u CultureInfo'nun statik bir özelliği olarak ayarlayıp vazgeçip kendi sınıflarınızdan birinin statik özelliği olarak ayarlayın. Bu, string'in varsayılan davranışını düzeltmez.Format veya StringFormat'ın ciltlerde düzgün çalışmasını sağlayın, ardından uygulamanızdaki tüm bağlantıları yeniden oluşturmak ve dönüştürücü kültürünü ayarlamak için uygulamanızın mantıksal ağacında yürüyün.


1
Austin'in cevabı zaten CultureInfo.DefaultThreadCurrentCulture'un AppDomain'in kültürünü değiştirecek şekilde ayarlanabileceği bilgisini verdi. CultureInfo.DefaultThreadCurrentUICulture, CurrentUICulture için CultureInfo.DefaultThreadCurrentCulture, CurrentCulture içindir. Gerçekten değeri doğrudan kodunuzdaki kayıt defterinden almak için bir neden yoktur. CurrentCulture'u belirli bir kültüre değiştirmek, ancak kullanıcının geçersiz kılmalarını korumak istiyorsanız, değeri geçersiz kılmadan önce CurrentCulture'un DateTimeFormat öğelerinden değeri almanız yeterlidir.
Eric MSFT

1
Kontrol etmek zorunda kalacak ama başarı olmadan denemeden hatırlıyorum, kayıt defterinden almaya yol açıyor. Gerçekten bu sebeple sebepsiz yere gideceğimi mi düşünüyorsun? Kayıt defteri erişimi, bu cesur yeni UAC dünyasında dev bir PITA'dır.
Peter Wone

4

ASP.NET5, yani ASPNETCORE için aşağıdakileri yapabilirsiniz 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")
    }
});

İşte size daha fazla bilgi veren bir dizi blog yazısı .


1
Bunu eski bir ASP.NET 2.0 sitesinde yapmanın bir yolunu aradım ve karşılaştırmada farklı bir Çekirdek siteyle ne kadar kolay yönettiğimi sinir bozucu! Çok uluslu bir şirketteyim ve dahili siteler için, tarih karışıklığını önlemek için tüm biçimlendirmelerimiz ABD'de. Ancak bu eski site en-US, en-CA ve fr-CA için oluşturulmuştur. Ve bir "hack-y" şekilde, bu yüzden düzeltmeye gittiğimde, tüm tip dönüşümleri veri katmanında patlar! (Fransız para değerleri "1 234,56 $" dır
Andrew S

1
@ Bağlantınız bozuldu. Belki bu , şu ve bu işaret ediyor
Fer R

4

Bu cevap @ rastating'in harika cevabı için biraz genişleme. Endişelenmeden .NET'in tüm sürümleri için aşağıdaki kodu kullanabilirsiniz:

    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

DefaultThreadCurrentCultureve DefaultThreadCurrentUICultureÇerçeve 4.0'da da mevcuttur, ancak bunlar Özel'dir. Yansıma kullanarak bunları kolayca ayarlayabilirsiniz. Bu, CurrentCultureaçıkça ayarlanmayan tüm evreleri etkiler (iş parçacıkları da çalışır).

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
Bu benim için çalıştı. Thread.CurrentThread.CurrentCulture = culture kullanmasına rağmen; Thread.CurrentThread.CurrentUICulture = kültür; Aynı görünmüyordu. Açıklık için bu, uygulamanın kendisinin kültürünü değiştirdiği bir WPF uygulamasında kullanılıyor, ancak diğer projelerde kullanıcı
kontrolleri

3

İşte c # MVC için çözüm:

  1. İlk olarak: Özel bir özellik oluşturun ve aşağıdaki gibi geçersiz kılın:

    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. İkinci olarak: App_Start uygulamasında FilterConfig.cs dosyasını bulun, bu özelliği ekleyin. (bu TÜM uygulama için geçerlidir)

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            // Add custom attribute here
            filters.Add(new CultureAttribute());
        }
    }    

Bu kadar !

Tüm uygulama yerine her denetleyici / eylem için kültür tanımlamak istiyorsanız, bu niteliği şu şekilde kullanabilirsiniz:

[Culture]
public class StudentsController : Controller
{
}

Veya:

[Culture]
public ActionResult Index()
{
    return View();
}

1

Tüm iş parçacıkları ve pencereler için CultureInfo ayarlamak için çalışma çözümü.

  1. App.xaml dosyasını açın ve uygulamaya başlangıç ​​olay işleyicisi atamak için yeni bir "Başlangıç" özelliği ekleyin:
<Application ........
             Startup="Application_Startup"
>
  1. App.xaml.cs dosyasını açın ve bu kodu oluşturulan başlangıç ​​işleyicisine ekleyin (bu durumda Application_Startup). Sınıf Uygulaması şöyle görünecektir:
    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;
        }
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.