क्या एक पूरे आवेदन के लिए संस्कृति स्थापित करने का एक तरीका है? सभी मौजूदा धागे और नए धागे?


177

क्या एक पूरे आवेदन के लिए संस्कृति स्थापित करने का एक तरीका है? सभी मौजूदा धागे और नए धागे?

हमारे पास एक डेटाबेस में संग्रहीत संस्कृति का नाम है, और जब हमारा आवेदन शुरू होता है, तो हम करते हैं

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

लेकिन, निश्चित रूप से, यह "खो" जाता है जब हम एक नए धागे में कुछ करना चाहते हैं। वहाँ है कि स्थापित करने का एक तरीका है CurrentCultureऔर CurrentUICultureपूरे आवेदन के लिए? ताकि नए सूत्र में वह संस्कृति भी आए? या जब भी कोई नया धागा बनाया जाता है, तो क्या मैं कुछ घटना को निकाल देता हूं?


4
यदि आप संसाधनों का उपयोग कर रहे हैं, तो आप इसे मैन्युअल रूप से बाध्य कर सकते हैं: Resource1.Culture = new System.Globalization.CultureInfo ("fr"); इस तरह हर बार जब आप एक स्ट्रिंग को पुनः प्राप्त करना चाहते हैं, तो यह स्थानीयकृत है और वापस लौटा है
रेजा एस

जवाबों:


196

.NET 4.5 में, आप CultureInfo.DefaultThreadCurrentCultureAppDomain की संस्कृति को बदलने के लिए संपत्ति का उपयोग कर सकते हैं ।

4.5 से पहले के संस्करणों के लिए आपको एक AppDomain की संस्कृति में हेरफेर करने के लिए प्रतिबिंब का उपयोग करना होगा। एक निजी स्थिर क्षेत्र है CultureInfo( m_userDefaultCulture.NET 2.0 mscorlib में, s_userDefaultCulture.NET 4.0 mscorlib में) जो नियंत्रित करता हैCurrentCulture यदि कोई थ्रेड स्वयं उस गुण को सेट नहीं है तो रिटर्न देता है।

यह मूल थ्रेड लोकेल को परिवर्तित नहीं करता है और यह संभवतः कोड को शिप करने का एक अच्छा विचार नहीं है जो इस तरह से संस्कृति को बदलता है। हालांकि यह परीक्षण के लिए उपयोगी हो सकता है।


9
ASP.NET अनुप्रयोगों में इस सेटिंग से सावधान रहें। AppDomain पर संस्कृति सेट करने से सभी उपयोगकर्ताओं के लिए संस्कृति सेट हो जाएगी। इसलिए यह अंग्रेजी उपयोगकर्ता के लिए जर्मन में जर्मन साइट देखने के लिए अच्छा नहीं होगा।
दिमित्र त्सोनव

2
मुझे एक ASP.NET अनुप्रयोग विरासत में मिला है जो केवल तभी काम करता है जब सभी संस्कृतियाँ अमेरिका में हों। यह एक ऐसा परिदृश्य है जहां यह सेटिंग उस दोष के ठीक होने तक समय के लिए एकदम सही है
डैनियल हिल्गारथ

37

इससे बहुत कुछ पूछा जाता है। मूल रूप से, .NET 4.0 के लिए नहीं, नहीं है। आपको इसे प्रत्येक नए थ्रेड (या ThreadPoolफ़ंक्शन) की शुरुआत में मैन्युअल रूप से करना होगा । आप शायद DB को हिट करने के लिए एक स्थिर फ़ील्ड में संस्कृति नाम (या सिर्फ संस्कृति ऑब्जेक्ट) संग्रहीत कर सकते हैं, लेकिन इसके बारे में है।


1
गुस्सा आ रहा है ... लगता है जैसे तुम सही हो, हेहे। इसलिए हम अब ऐसा करते हैं (और संस्कृति एक स्थिर वर्ग है), लेकिन हमारे पास अभी भी कुछ धागों की समस्या है, जिन पर हमारा नियंत्रण नहीं है। जैसे Microsoft रिपोर्ट व्यूअर में थ्रेड को संसाधित करना। हालांकि आसपास एक काम मिला। जानकारी के लिए धन्यवाद :)
Svish

8
यह वास्तव में कष्टप्रद है :( यह अच्छा होगा यदि आपके आवेदन के लिए वर्तमान (यूआई) संस्कृति को स्वचालित रूप से सेट करने का एक तरीका है और सभी नए धागे उस मूल्य को उठाते हैं।
जेडीजा

1
जब से मैंने इसके साथ काम किया है तब से यह बहुत लंबा है इसलिए मुझे याद नहीं है कि हमने क्या किया। लेकिन मुझे लगता है कि यह हो सकता है कि हम रिपोर्ट दर्शक को भेजे गए डेटासेट में तारीखों का उपयोग करने के बजाय, हमने तारीख को एक स्ट्रिंग में पहले स्वरूपित किया था, हमने उस संस्कृति का उपयोग किया था जिसे हमने एप्लिकेशन में सेट किया था। तब वास्तव में इससे कोई फर्क नहीं पड़ा कि रिपोर्ट रेंडरिंग थ्रेड्स ने गलत संस्कृति का उपयोग किया। इसलिए हमने गलत संस्कृति का उपयोग करते हुए थ्रेड्स के साथ समस्या के आसपास काम नहीं किया। हमने सिर्फ तारीखों को गलत तरीके से स्वरूपित करने की समस्या के आसपास काम किया :)
Svish

2
हमारे ऐप में, मैंने थ्रेड्स को "कैप्चर" करने की कोशिश की (कुछ स्थानों से एक विशेष विधि को कॉल करके) और उन्हें बाद के उपयोग के लिए एक संग्रह में संग्रहीत किया (इस मामले में संस्कृति सेट करने के लिए), जो अब तक काम कर रहा है।
श्री टीए

1
क्या आप सत्र में कल्चरिनफ़ॉफ़ ऑब्जेक्ट को संग्रहीत नहीं कर सकते हैं और (यदि आप मास्टरपेज़ का उपयोग कर रहे हैं) तो अपने मास्टरपेज कोडहैंड में इसके लिए जाँच करें और वर्तमान थ्रेड सेट करें?
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;
    }
}

अब हर बार जब आप इस संसाधन के भीतर अपने व्यक्तिगत स्ट्रिंग का उल्लेख करते हैं, तो यह निर्दिष्ट संसाधनसंस्कृति के साथ संस्कृति (थ्रेड या प्रक्रिया) को ओवरराइड करता है।

आप या तो भाषा को "fr", "de" आदि के रूप में निर्दिष्ट कर सकते हैं या भाषा कोड को 0x0409 में एन-यूएस के लिए डाल सकते हैं या आईटी के लिए 0x0410 पर रख सकते हैं। भाषा कोड की पूरी सूची के लिए कृपया देखें: भाषा पहचानकर्ता और स्थान


इसे अशक्त करने के लिए " Resource1.Culture = Null;
अप्राप्य

8

.Net 4.5 और इससे अधिक के लिए आपको उपयोग करना चाहिए

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

6

वास्तव में आप डिफ़ॉल्ट थ्रेड संस्कृति और UI संस्कृति सेट कर सकते हैं, लेकिन केवल फ्रेमवर्क 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 की कन्वर्ट विधि में एक ब्रेकपॉइंट डालें। CultureInfo.CurrentUICulture एन-यूएस होना बंद हो गया और इसके बजाय एन-एयू पूरा हो गया जो कि मेरी छोटी सी हैक के साथ पूरा हो गया ताकि इसे शोर्टटाइमपैटर्न के लिए क्षेत्रीय सेटिंग्स का सम्मान किया जा सके।

हुर्रे, दुनिया में सब ठीक है! या नहीं। कन्वर्ट विधि में दिया गया संस्कृति पैरामीटर अभी भी एन-यूएस है। एर्म, डब्ल्यूटीएफ ?! लेकिन यह एक शुरुआत है। कम से कम इस तरह से

  • जब आपका ऐप लोड होता है तो आप एक बार यूआई संस्कृति को ठीक कर सकते हैं
  • यह हमेशा से सुलभ है CultureInfo.CurrentUICulture
  • string.Format("{0}", DateTime.Now) आपकी अनुकूलित क्षेत्रीय सेटिंग्स का उपयोग करेगा

यदि आप फ्रेमवर्क के संस्करण ४.५ का उपयोग नहीं कर सकते हैं तो संस्कृतिइन्फो की स्थैतिक संपत्ति के रूप में करंटीकल्चर की स्थापना पर छोड़ दें और इसे अपनी खुद की कक्षाओं में से एक स्थिर संपत्ति के रूप में सेट करें। यह स्ट्रिंग के डिफ़ॉल्ट व्यवहार को ठीक नहीं करेगा। स्टॉर्मफॉर्म या स्ट्रिंगरफॉर्म को बाइंडिंग में ठीक से काम करने के लिए फिर अपने ऐप के सभी पेड़ों को फिर से बनाने के लिए अपने ऐप के तार्किक पेड़ को चलाएं और अपनी कनवर्टर संस्कृति सेट करें।


1
ऑस्टिन के उत्तर ने पहले ही यह जानकारी प्रदान कर दी थी कि AppInomain की संस्कृति को बदलने के लिए CultureInfo.DefaultThreadCurrentCulture सेट किया जा सकता है। CultureInfo.DefaultThreadCurrentUICulture, संस्कृतिइन्फोर्टर के रूप में CurrentUICulture है। वास्तव में आपके कोड में रजिस्ट्री से सीधे मूल्य प्राप्त करने का कोई कारण नहीं है। यदि आप CurrentCulture को कुछ विशिष्ट संस्कृति में बदलना चाहते हैं, लेकिन उपयोगकर्ता को ओवरराइड करते हैं, तो आपको वर्तमान से अधिक वर्तमान CurrentCulture के DateTimeFormat से इसे प्राप्त करने से पहले मान प्राप्त करना होगा।
एरिक MSFT

1
मुझे जांच करनी होगी, लेकिन मैं यह याद रखना चाहता हूं कि सफलता के बिना, यह रजिस्ट्री से प्राप्त करने के लिए अग्रणी है। क्या आप वास्तव में सोचते हैं कि मैं बिना किसी कारण के सभी परेशानी में जाऊंगा? यूएसी की इस बहादुर नई दुनिया में रजिस्ट्री एक्सेस एक विशाल पीटीए है।
पीटर वॉन

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-CA और fr-CA के लिए स्थापित है। और "हैक-वाई" तरीके से, इसलिए जब मैं इसे ठीक करने के लिए जाता हूं, तो उनके सभी प्रकार के रूपांतरण डेटा परत में उड़ जाते हैं! (फ्रेंच मनी वैल्यू "1 234,56 $"
एंड्रयू एस

1
@ आपका लिंक टूट गया है। शायद यह की ओर इशारा इस , यह और इस
फेर आर

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 में भी मौजूद हैं, लेकिन वे निजी हैं। प्रतिबिंब का उपयोग करके आप उन्हें आसानी से सेट कर सकते हैं। यह उन सभी थ्रेड्स को प्रभावित करेगा जहां 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
यह एक मेरे लिए काम किया। यद्यपि थ्रेड का उपयोग करना। CurrentThread.CurrentCulture = संस्कृति; थ्रेड। CurrentThread.CurrentUICulture = संस्कृति; जो एक ही नहीं दिखता है। स्पष्टता के लिए इसका उपयोग WPF ऐप में किया जा रहा है, जहाँ ऐप स्वयं अपनी संस्कृति को बदल रहा था, लेकिन अन्य परियोजनाओं में usercontrols ब्राउज़र संस्कृति का उपयोग कर रहे थे, न कि उपयोगकर्ता द्वारा चुनी गई संस्कृति
chillfire

3

यहाँ सी # 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();
}

1

सभी थ्रेड्स और विंडो के लिए CultureInfo सेट करने के लिए कार्य समाधान।

  1. App.xaml फ़ाइल खोलें और ऐप के लिए स्टार्टअप इवेंट हैंडलर असाइन करने के लिए एक नया "स्टार्टअप" विशेषता जोड़ें:
<Application ........
             Startup="Application_Startup"
>
  1. App.xaml.cs फ़ाइल खोलें और इस कोड को स्टार्टअप हैंडलर (इस मामले में Application_Startup) में जोड़ें। क्लास ऐप इस तरह दिखेगा:
    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;
        }
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.