अपवाद संदेश अंग्रेजी में?


298

हम किसी भी अपवाद को लॉग कर रहे हैं जो हमारे सिस्टम में Exception.Message को एक फ़ाइल में लिखकर होता है। हालांकि, वे क्लाइंट की संस्कृति में लिखे गए हैं। और तुर्की की त्रुटियां मेरे लिए बहुत मायने नहीं रखती हैं।

तो हम उपयोगकर्ताओं की संस्कृति को बदलने के बिना अंग्रेजी में किसी भी त्रुटि संदेश को कैसे लॉग कर सकते हैं?


8
आप इस तरह से क्यों नहीं स्वाहा हो सकते हैं: CultureInfo oldCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture ("en"); // थ्रो न्यू एक्ससेप्शन यहाँ => कल्चर अंग्रेजी थ्रेड में है। CurrentThread.CurrentCulture = oldCulture;
CheGueVerra

93
मुझे पता है कि कोई भी डेवलपर नहीं है, जो गैर-अंग्रेजी अपवाद संदेशों के लिए खुश है: S ..
Zéiksz

3
@ Zéiksz अंग्रेजी बोलने वाले देशों से परे है और आप उनमें से कई मिलेंगे: डी। समस्या गैर-अंग्रेजी पाठ नहीं है, समस्या एक ऐसी भाषा है जिसे आप समझ नहीं सकते हैं। आपकी मूल भाषा (उचित अनुवाद मानते हुए) में संदेश पूरी तरह से ठीक हैं।
एलेजांद्रो

31
@Alejandro गूगल के लिए एक मूल भाषा से अंग्रेजी में एक अपवाद संदेश का अनुवाद करने के लिए यह गधा में भी एक बड़ा दर्द है। IMHO।
एंटोनी मेल्टज़ाइम

18
Microsoft में किस बेवकूफ को त्रुटि संदेशों का अनुवाद करने का विचार है जो केवल डेवलपर्स के लिए हैं। यहां तक ​​कि ऐसे शब्द जो प्रोग्रामिंग भाषा में उपयोग किए जाते हैं जैसे एक शब्दकोश में एक कुंजी का अनुवाद किया जाता है। (कुंजी को शब्दकोश में नहीं पाया जाता है, डच में बिब्लियोथेकेक में नी जियोवॉन्डेन में स्लीटेल बन जाता है)। मैं इसके लिए OS भाषा नहीं बदलना चाहता ...
Roel

जवाबों:


66

इस मुद्दे पर आंशिक रूप से काम किया जा सकता है। फ़्रेमवर्क अपवाद कोड वर्तमान थ्रेड लोकेल के आधार पर, अपने संसाधनों से त्रुटि संदेशों को लोड करता है। कुछ अपवादों के मामले में, यह उस समय होता है जब संदेश संपत्ति एक्सेस की जाती है।

उन अपवादों के लिए, आप संदेश के पूर्ण अमेरिकी अंग्रेजी संस्करण को संक्षेप में थ्रेड लोकेल को en-US पर ले जा सकते हैं जबकि इसे लॉग-इन कर सकते हैं (मूल उपयोगकर्ता लोकेल को पहले से ही सहेज कर रख सकते हैं और बाद में इसे पुनर्स्थापित कर सकते हैं)।

एक अलग धागे पर ऐसा करना और भी बेहतर है: यह सुनिश्चित करता है कि कोई दुष्प्रभाव नहीं होगा। उदाहरण के लिए:

try
{
  System.IO.StreamReader sr=new System.IO.StreamReader(@"c:\does-not-exist");
}
catch(Exception ex)
{
  Console.WriteLine(ex.ToString()); //Will display localized message
  ExceptionLogger el = new ExceptionLogger(ex);
  System.Threading.Thread t = new System.Threading.Thread(el.DoLog);
  t.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
  t.Start();
}

जहाँ ExceptionLogger वर्ग कुछ इस तरह दिखता है:

class ExceptionLogger
{
  Exception _ex;

  public ExceptionLogger(Exception ex)
  {
    _ex = ex;
  }

  public void DoLog()
  {
    Console.WriteLine(_ex.ToString()); //Will display en-US message
  }
}

हालांकि, जो के रूप में सही ढंग से इस उत्तर के पहले संशोधन पर एक टिप्पणी में बताते हैं, कुछ संदेश पहले से ही (आंशिक रूप से) भाषा के संसाधनों से लोड किए जाते हैं, जब अपवाद छोड़ दिया जाता है।

उदाहरण के लिए, ArgumentNullException ("foo") अपवाद को फेंके जाने पर उत्पन्न संदेश के 'पैरामीटर को शून्य नहीं किया जा सकता' पर लागू होता है। उन मामलों में, संदेश अभी भी (आंशिक रूप से) स्थानीयकृत दिखाई देगा, यहां तक ​​कि उपरोक्त कोड का उपयोग करते समय भी।

अव्यवहारिक हैक्स का उपयोग करने के अलावा, जैसे कि एन-यूएस लोकेल के साथ एक थ्रेड पर अपने सभी गैर-यूआई कोड को शुरू करने के लिए, वहाँ ऐसा नहीं लगता कि आप इसके बारे में बहुत कुछ कर सकते हैं: .NET फ्रेमवर्क अपवाद कोड में कोई भी नहीं है त्रुटि संदेश लोकेल को ओवरराइड करने की सुविधाएं।


10
आपका उदाहरण FileNotFoundException के लिए काम करता है, क्योंकि संदेश संसाधन को तब प्राप्त किया जाता है जब संदेश संपत्ति तक पहुँचा जाता है, न कि जब अपवाद फेंका जाता है। लेकिन यह सभी अपवादों के लिए सही नहीं है (उदाहरण के लिए नया तर्क फेंकने की कोशिश करो। अपवाद ("नाम"))
जो

3
मैं उलझन में हूं। मैंने आपके उत्तर का अनुसरण करने की कोशिश की है और इसका परीक्षण करने के लिए मुझे अपना अपवाद फ्रेंच में चाहिए था, इसलिए मैंने किया t.CurrentUICulture = new System.Globalization.CultureInfo("fr-FR");और t.CurrentCulture = new System.Globalization.CultureInfo("fr-FR");फिर भी, परिणामी अपवाद अंग्रेजी में था ...
विटालिबी

7
@VitalyB स्थानीय अपवाद पाठ .NET .NET भाषा पैक का हिस्सा हैं। इसलिए यदि आपके पास फ्रेंच भाषा पैक स्थापित नहीं है, तो आपको अनुवादित पाठ नहीं मिलेंगे।
डैनियल रोज

7
.NET 4.5 के साथ कम से कम सभी अपवाद त्वरित हैं, Environment.GetResourceString("...")इसलिए आपका समाधान अब काम नहीं करता है। सबसे अच्छी बात यह है कि अपने स्वयं के (अंग्रेजी) संदेश पाठ के साथ कस्टम अपवाद को फेंक दें और पुराने को बनाए रखने के लिए इनर एक्सेप्शन प्रॉपर्टी का उपयोग करें।
वेबर 2k6

1
अपवाद प्रकार के नाम पाने के लिए चिंतन आसान हो सकता है।
गुइलेर्मो प्रांडी

67

आप मूल अपवाद संदेश के लिए unlocalize.com पर खोज सकते हैं


5
कुछ चीनी अपवाद संदेशों की खोज करने की कोशिश की, हमेशा मुझे बताया No records found
टायलर लॉन्ग

1
खराब चुनाव। जब मैं Google Analytics (या अन्य क्लाउड सेवा) पर अपना अपवाद भेजता हूं, तो मेरे पास अपवादों के अलग-अलग समूह होंगे, लेकिन अलग-अलग भाषाएं। और मैं प्रत्येक अपवाद की गिनती के आधार पर क्रमबद्ध नहीं कर पाऊंगा, क्योंकि यह वास्तविक गिनती (अंग्रेजी में 100, चीनी में 77, कोरियाई में 80 ... आदि) को प्रतिबिंबित नहीं करता है
आर्टेमियस

मुझे याद है कि इस खूबसूरत वेबसाइट को खोजने के लिए कई बार जब मैंने केवल Google में स्थानीय अपवाद संदेशों को डंप किया था, अब यह उपलब्ध नहीं है।
मार्टिन ब्रौन

40

एक विवादास्पद बिंदु शायद, लेकिन संस्कृति को सेट करने के बजाय en-US, आप इसे सेट कर सकते हैं Invariant। में Invariantसंस्कृति, त्रुटि संदेश अंग्रेजी में हैं।

Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;

यह पक्षपाती नहीं दिखने का फायदा है, खासकर गैर-अमेरिकी अंग्रेजी बोलने वाले स्थानों के लिए। (उर्फ सहकर्मियों की भद्दी टिप्पणी से बचता है)


1
हमें अपने ASP.NET प्रोजेक्ट में इन लाइनों को कहाँ लिखना चाहिए? धन्यवाद।
जेसन

2
मैं सबसे ऊपर, Application_Start में सुझाव देने जा रहा हूं। यह पूरे प्रोजेक्ट को अंग्रेजी में चलाएगा। यदि यह केवल त्रुटि संदेशों के लिए है जो आप चाहते हैं, तो आप एक कवर फ़ंक्शन बना सकते हैं और प्रत्येक में कॉल कर सकते हैं catch
MPelletier

5
क्या यह भी मानक संदेश बॉक्स बटन अंग्रेजी में नहीं होगा, हालांकि? वह वांछित व्यवहार नहीं हो सकता है।
Nyerguds

12

यहां समाधान है कि किसी भी कोडिंग की आवश्यकता नहीं है और अपवादों के ग्रंथों के लिए भी काम करता है जो हमारे लिए कोड द्वारा बदलने में सक्षम होने के लिए बहुत जल्दी लोड हो जाते हैं (उदाहरण के लिए, mscorlib में)।

यह हमेशा हर मामले में लागू नहीं हो सकता है (यह आपके सेटअप पर निर्भर करता है क्योंकि आपको मुख्य .exe फ़ाइल को एक तरफ .config बनाने में सक्षम होना चाहिए) लेकिन यह मेरे लिए काम करता है। तो, बस एक बनाने के app.configदेव में, (या एक [myapp].exe.configया web.configउत्पादन में) उदाहरण के लिए निम्नलिखित लाइनों में शामिल है कि:

<configuration>
  ...
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="mscorlib.resources" publicKeyToken="b77a5c561934e089"
                          culture="fr" /> <!-- change this to your language -->

        <bindingRedirect oldVersion="1.0.0.0-999.0.0.0" newVersion="999.0.0.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Xml.resources" publicKeyToken="b77a5c561934e089"
                          culture="fr" /> <!-- change this to your language -->

        <bindingRedirect oldVersion="1.0.0.0-999.0.0.0" newVersion="999.0.0.0"/>
      </dependentAssembly>

      <!-- add other assemblies and other languages here -->

    </assemblyBinding>
  </runtime>
  ...
</configuration>

यह क्या बताता है कि mscorlib'' संसाधनों और संसाधनों के लिए असेंबली बाइंडिंग को System.Xml1 और 999 के बीच के संस्करणों के लिए पुनर्निर्देशित किया गया है , फ्रेंच में (संस्कृति के लिए सेट है)fr असेंबली में " के ) असेंबली के लिए ... मौजूद नहीं है (एक मनमाना संस्करण 999)।

इसलिए जब सीएलआर इन दो असेंबली (mscorlib और System.xml) के लिए फ्रेंच संसाधनों की तलाश करेगा, तो यह उन्हें नहीं मिलेगा और इनायत से अंग्रेजी में आएगा। आपके संदर्भ और परीक्षण के आधार पर, आप इन रीडायरेक्ट (ऐसी असेंबली जिसमें स्थानीय संसाधन शामिल हैं) में अन्य असेंबली जोड़ना चाहते हैं।

बेशक, मुझे नहीं लगता कि यह Microsoft द्वारा समर्थित है, इसलिए अपने जोखिम पर उपयोग करें। ठीक है, यदि आप किसी समस्या का पता लगाते हैं, तो आप इस विन्यास को हटा सकते हैं और जांच सकते हैं कि यह असंबंधित है।


1
काम करता है जब परीक्षण-धावक उपकरणों से अंग्रेजी आउटपुट की आवश्यकता होती है।
SMG

इस की कोशिश की, लेकिन यह मेरे लिए काम नहीं किया। क्या अन्य संसाधन फ़ाइलें .net में हैं? मुझे वे कहां मिल सकते हैं?
BluE

1
C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 में देखें। हर भाषा में 2 अक्षर का फोल्डर होता है। ऊपर दिए गए उत्तर में "fr" को वास्तविक भाषा के साथ याद रखें जिसका उपयोग किया जा रहा है। "नो" गर्लफ्रेंड, "डा" फॉर डैट, "sv" फॉर
सिन

एक पूर्ण सूची बनाने के लिए, उस फ़ोल्डर में एक नज़र डालें। इसकी लगभग 120 संसाधन फाइलें हैं। उनमें से प्रत्येक को कॉन्फ़िगर में जोड़ें। यह अब के लिए विंडोज 10 और नए के लिए एकमात्र समाधान प्रतीत होता है, क्योंकि अब नए विंडोज़ में .Net भाषा पैक की स्थापना रद्द करने का कोई तरीका नहीं है (इसका ओएस का हिस्सा)। यह भी अब GAC में रखा गया है, इसलिए उन भाषा फ़ोल्डर को हटाने से काम नहीं लगता है।
वुल्फ 5

10

विंडोज के लिए यूआई भाषा होनी चाहिए जिसे आप इंस्टॉल करना चाहते हैं। यह नहीं है, यह जादुई तरीके से यह जानने का कोई तरीका नहीं है कि अनुवादित संदेश क्या है।

7-परम विंडो में, परम-पीटी-पीटी स्थापित होने के साथ, निम्न कोड:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("pt-PT");
string msg1 = new DirectoryNotFoundException().Message;

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
string msg2 = new FileNotFoundException().Message;

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
string msg3 = new FileNotFoundException().Message;

Pt-PT, en-US और en-US में संदेश तैयार करता है। चूंकि कोई फ्रांसीसी संस्कृति फ़ाइलों को स्थापित नहीं किया गया है, इसलिए यह विंडोज़ डिफ़ॉल्ट (स्थापित) भाषा में डिफ़ॉल्ट है।


यह समस्या हल हो गई है। मेरी स्थिति में पोलिश UI, Vistalizator प्रोग्राम का उपयोग करते हुए, MUI भाषा संकुल ~ 260MB स्थापित करता है।
Krzysztof Szynter

5

मुझे पता है कि यह एक पुराना विषय है, लेकिन मुझे लगता है कि मेरा समाधान किसी ऐसे व्यक्ति के लिए काफी प्रासंगिक हो सकता है, जो वेब खोज में इस पर ठोकर खाता है:

अपवाद लकड़हारा में आप ex.GetType.ToString लॉग कर सकते हैं, जो अपवाद वर्ग के नाम को बचाएगा। मैं उम्मीद करूंगा कि एक वर्ग का नाम भाषा से स्वतंत्र होना चाहिए और इसलिए इसे हमेशा अंग्रेजी में दर्शाया जाएगा (उदाहरण के लिए "System.FileNotFoundException"), हालांकि वर्तमान में मेरे पास एक विदेशी भाषा प्रणाली तक पहुंच का परीक्षण करने के लिए नहीं है। विचार।

यदि आप वास्तव में त्रुटि संदेश पाठ चाहते हैं, तो आप जो भी भाषा पसंद करते हैं उसमें सभी संभावित अपवाद वर्ग नामों और उनके समकक्ष संदेशों का एक शब्दकोश बना सकते हैं, लेकिन अंग्रेजी के लिए मुझे लगता है कि वर्ग नाम पूरी तरह से पर्याप्त है।


5
काम नहीं करता है। मैं एक InvalidOperationException, द्वारा फेंक दिया गया System.Xml.XmlWellFormedWriter। आप यह अनुमान लगाने की कोशिश करते हैं कि संदेश को पढ़े बिना क्या विशिष्ट त्रुटि हुई। एक हजार अलग चीजें हो सकती हैं।
Nyerguds 14

4
CultureInfo oldCI = Thread.CurrentThread.CurrentCulture;

Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture ("en-US");
Thread.CurrentThread.CurrentUICulture=new CultureInfo("en-US");
try
{
  System.IO.StreamReader sr=new System.IO.StreamReader(@"c:\does-not-exist");
}
catch(Exception ex)
{
  Console.WriteLine(ex.ToString())
}
Thread.CurrentThread.CurrentCulture = oldCI;
Thread.CurrentThread.CurrentUICulture = oldCI;

काम के बिना।

Tks :)


तुम भूल गए;
KansaiRobot

4

Thread.CurrentThread.CurrentUICultureअपवादों को स्थानीय बनाने के लिए सेटिंग का उपयोग किया जाएगा। यदि आपको दो प्रकार के अपवादों की आवश्यकता है (उपयोगकर्ता के लिए एक, आपके लिए) आप अपवाद-संदेश का अनुवाद करने के लिए निम्न फ़ंक्शन का उपयोग कर सकते हैं। यह मूल-पाठ के लिए .NET-लाइब्रेरी संसाधनों में संसाधन-कुंजी प्राप्त करने के लिए खोज कर रहा है और फिर अनुवादित मान लौटाता है। लेकिन एक कमजोरी यह है कि मुझे अभी तक एक अच्छा समाधान नहीं मिला: संदेश, जिसमें संसाधन में {0} शामिल नहीं है। अगर किसी के पास कोई अच्छा उपाय है तो मैं आभारी रहूंगा।

public static string TranslateExceptionMessage(Exception ex, CultureInfo targetCulture)
{
    try
    {
        Assembly assembly = ex.GetType().Assembly;
        ResourceManager resourceManager = new ResourceManager(assembly.GetName().Name, assembly);
        ResourceSet originalResources = resourceManager.GetResourceSet(Thread.CurrentThread.CurrentUICulture, createIfNotExists: true, tryParents: true);
        ResourceSet targetResources = resourceManager.GetResourceSet(targetCulture, createIfNotExists: true, tryParents: true);
        foreach (DictionaryEntry originalResource in originalResources)
            if (originalResource.Value.ToString().Equals(ex.Message.ToString(), StringComparison.Ordinal))
                return targetResources.GetString(originalResource.Key.ToString(), ignoreCase: false); // success

    }
    catch { }
    return ex.Message; // failed (error or cause it's not smart enough to find texts with '{0}'-patterns)
}

यदि अपवाद स्वरूपित पैरामीटर में काम करने वाला नहीं है।
निक बेर्डी

हां, जैसा कि मैंने कहा: "लेकिन एक कमजोरी मुझे अभी तक एक अच्छा समाधान नहीं मिली: संदेश, जिसमें संसाधनों में {0} शामिल नहीं होगा। अगर किसी के पास अच्छा समाधान है तो मैं आभारी रहूंगा।"
भंवर852456

3

.NET फ्रेमवर्क दो भागों में आता है:

  1. .NET फ्रेमवर्क ही
  2. .NET फ्रेमवर्क भाषा पैक

सभी पाठ (पूर्व अपवाद संदेश, संदेश लेबल पर बटन लेबल आदि) अंग्रेजी में .NET फ्रेमवर्क में ही हैं। भाषा पैक में स्थानीयकृत ग्रंथ हैं।

आपकी सटीक स्थिति के आधार पर, भाषा पैक को अनइंस्टॉल करने का एक उपाय होगा (यानी ग्राहक को ऐसा करने के लिए कहें)। उस स्थिति में, अपवाद ग्रंथ अंग्रेजी में होंगे। हालाँकि, ध्यान दें कि अन्य सभी रूपरेखा-प्रदत्त पाठ अंग्रेजी के साथ-साथ (संदेशबॉक्स पर बटन लेबल, ApplicationCommands के लिए कीबोर्ड शॉर्टकट) भी होंगे।


धन्यवाद!! मुझे यह विडंबना लगता है कि अनइंस्टॉल डायलॉग अनइंस्टॉलिंग पैक की भाषा में है न कि स्थानीय भाषा में। साइड नोट: भाषा पैक हर कुछ महीनों में लौटते हुए प्रतीत होते हैं। मैंने काम नहीं किया है, लेकिन मैं एक अपडेट / उन्नयन का अनुमान लगा रहा हूं
चोको स्मिथ

@ChocoSmith विंडोज अपडेट के माध्यम से .NET फ्रेमवर्क के हर अपडेट के साथ, भाषा पैक फिर से स्थापित होता है।
डैनियल रोज 10

5
ग्राहकों को अपनी भाषा के लिए भाषा पैक की स्थापना रद्द करने के लिए कहना एक व्यवहार्य समाधान नहीं है।
Nyerguds

2

मैं इनमें से एक दृष्टिकोण की कल्पना करूंगा:

  1. अपवाद केवल आपके द्वारा कभी-कभी पढ़े जाते हैं, अर्थात वे एक क्लाइंट फ़ीचर नहीं हैं, इसलिए आप हार्डवेयर्ड गैर स्थानीयकृत स्ट्रिंग्स का उपयोग कर सकते हैं जो आपके तुर्की मोड में चलने पर परिवर्तित नहीं होंगे।

  2. 0x00000001प्रत्येक त्रुटि के साथ एक त्रुटि कोड शामिल करें ताकि आप इसे आसानी से एक अंग्रेजी तालिका में देख सकें।


9
जब वे .net ढांचे के आंतरिक घटकों द्वारा फेंके गए अपवाद हैं तो इससे बहुत मदद नहीं मिलेगी । यह पूरी समस्या आपके द्वारा खुद को फेंकने वाले अपवादों पर लागू नहीं होती है; जाहिर है प्रोग्रामर चुनता है कि उन लोगों के साथ क्या संदेश शामिल किया जाए ।
Nyerguds

1

Undercover1989 उत्तर के आधार पर, लेकिन खाता मापदंडों में और जब संदेश कई संसाधन तार (जैसे तर्क अपवाद) से बना होता है।

public static string TranslateExceptionMessage(Exception exception, CultureInfo targetCulture)
{
    Assembly a = exception.GetType().Assembly;
    ResourceManager rm = new ResourceManager(a.GetName().Name, a);
    ResourceSet rsOriginal = rm.GetResourceSet(Thread.CurrentThread.CurrentUICulture, true, true);
    ResourceSet rsTranslated = rm.GetResourceSet(targetCulture, true, true);

    var result = exception.Message;

    foreach (DictionaryEntry item in rsOriginal)
    {
        if (!(item.Value is string message))
            continue;

        string translated = rsTranslated.GetString(item.Key.ToString(), false);

        if (!message.Contains("{"))
        {
            result = result.Replace(message, translated);
        }
        else
        {
            var pattern = $"{Regex.Escape(message)}";
            pattern = Regex.Replace(pattern, @"\\{([0-9]+)\}", "(?<group$1>.*)");

            var regex = new Regex(pattern);

            var replacePattern = translated;
            replacePattern = Regex.Replace(replacePattern, @"{([0-9]+)}", @"${group$1}");
            replacePattern = replacePattern.Replace("\\$", "$");

            result = regex.Replace(result, replacePattern);
        }
    }

    return result;
}

1

मेरे पास एक ही स्थिति है, और सभी उत्तर जो मुझे यहां मिले और कहीं और मदद नहीं मिली या संतोषजनक नहीं थे:

Thread.CurrentUICulture.Net अपवाद की भाषा बदल जाती है, लेकिन यह के लिए नहीं है Win32Exception, जो Windows यूआई खुद की भाषा में विंडोज संसाधनों का उपयोग करता। इसलिए मैं Win32Exceptionजर्मन के बजाय अंग्रेजी के संदेशों को मुद्रित करने में कभी कामयाब नहीं हुआ, यहां तक ​​कि अंग्रेजी में Win32Exception प्राप्त करने केFormatMessage() तरीके के रूप में वर्णित करके भी नहीं
?

इसलिए मैंने अपना स्वयं का समाधान बनाया, जो बाहरी फ़ाइलों में विभिन्न भाषाओं के लिए मौजूदा अपवाद संदेशों के बहुमत को संग्रहीत करता है। आपको अपनी इच्छित भाषा में बहुत सटीक संदेश नहीं मिलेगा, लेकिन आपको उस भाषा में एक संदेश मिलेगा, जो वर्तमान में आपके द्वारा प्राप्त की गई जानकारी से बहुत अधिक है (जो कि आपको समझ में नहीं आने वाली भाषा में संदेश है)।

इस वर्ग के स्थिर कार्यों को अलग-अलग भाषाओं के साथ विंडोज इंस्टॉलेशन पर निष्पादित किया जा सकता है: CreateMessages()संस्कृति-विशिष्ट ग्रंथ बनाता है जो
SaveMessagesToXML()उन्हें कई XML फ़ाइलों को बचाता है जैसे भाषाएं बनाई जाती हैं या लोड की जाती हैं।
LoadMessagesFromXML() भाषा-विशिष्ट संदेशों के साथ सभी XML फ़ाइलों को जाता है

अलग-अलग भाषाओं के साथ अलग-अलग विंडोज इंस्टॉलेशन पर XML फाइलें बनाते समय, आपके पास जल्द ही वे सभी भाषाएं होंगी जिनकी आपको जरूरत है।
हो सकता है कि जब आप एकाधिक MUI भाषा पैक स्थापित करते हैं, तो आप 1 विंडोज पर अलग-अलग भाषाओं के लिए टेक्स्ट बना सकते हैं, लेकिन मैंने अभी तक उसका परीक्षण नहीं किया है।

VS2008 के साथ परीक्षण किया गया, उपयोग के लिए तैयार है। टिप्पणियों और सुझावों का स्वागत है!

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Threading;
using System.Xml;

public struct CException
{
  //----------------------------------------------------------------------------
  public CException(Exception i_oException)
  {
    m_oException = i_oException;
    m_oCultureInfo = null;
    m_sMessage = null;
  }

  //----------------------------------------------------------------------------
  public CException(Exception i_oException, string i_sCulture)
  {
    m_oException = i_oException;
    try
    { m_oCultureInfo = new CultureInfo(i_sCulture); }
    catch
    { m_oCultureInfo = CultureInfo.InvariantCulture; }
    m_sMessage = null;
  }

  //----------------------------------------------------------------------------
  public CException(Exception i_oException, CultureInfo i_oCultureInfo)
  {
    m_oException = i_oException;
    m_oCultureInfo = i_oCultureInfo == null ? CultureInfo.InvariantCulture : i_oCultureInfo;
    m_sMessage = null;
  }

  //----------------------------------------------------------------------------
  // GetMessage
  //----------------------------------------------------------------------------
  public string GetMessage() { return GetMessage(m_oException, m_oCultureInfo); }

  public string GetMessage(String i_sCulture) { return GetMessage(m_oException, i_sCulture); }

  public string GetMessage(CultureInfo i_oCultureInfo) { return GetMessage(m_oException, i_oCultureInfo); }

  public static string GetMessage(Exception i_oException) { return GetMessage(i_oException, CultureInfo.InvariantCulture); }

  public static string GetMessage(Exception i_oException, string i_sCulture)
  {
    CultureInfo oCultureInfo = null;
    try
    { oCultureInfo = new CultureInfo(i_sCulture); }
    catch
    { oCultureInfo = CultureInfo.InvariantCulture; }
    return GetMessage(i_oException, oCultureInfo);
  }

  public static string GetMessage(Exception i_oException, CultureInfo i_oCultureInfo)
  {
    if (i_oException == null) return null;
    if (i_oCultureInfo == null) i_oCultureInfo = CultureInfo.InvariantCulture;

    if (ms_dictCultureExceptionMessages == null) return null;
    if (!ms_dictCultureExceptionMessages.ContainsKey(i_oCultureInfo))
      return CreateMessage(i_oException, i_oCultureInfo);

    Dictionary<string, string> dictExceptionMessage = ms_dictCultureExceptionMessages[i_oCultureInfo];
    string sExceptionName = i_oException.GetType().FullName;
    sExceptionName = MakeXMLCompliant(sExceptionName);
    Win32Exception oWin32Exception = (Win32Exception)i_oException;
    if (oWin32Exception != null)
      sExceptionName += "_" + oWin32Exception.NativeErrorCode;
    if (dictExceptionMessage.ContainsKey(sExceptionName))
      return dictExceptionMessage[sExceptionName];
    else
      return CreateMessage(i_oException, i_oCultureInfo);
  }

  //----------------------------------------------------------------------------
  // CreateMessages
  //----------------------------------------------------------------------------
  public static void CreateMessages(CultureInfo i_oCultureInfo)
  {
    Thread oTH = new Thread(new ThreadStart(CreateMessagesInThread));
    if (i_oCultureInfo != null)
    {
      oTH.CurrentCulture = i_oCultureInfo;
      oTH.CurrentUICulture = i_oCultureInfo;
    }
    oTH.Start();
    while (oTH.IsAlive)
    { Thread.Sleep(10); }
  }

  //----------------------------------------------------------------------------
  // LoadMessagesFromXML
  //----------------------------------------------------------------------------
  public static void LoadMessagesFromXML(string i_sPath, string i_sBaseFilename)
  {
    if (i_sBaseFilename == null) i_sBaseFilename = msc_sBaseFilename;

    string[] asFiles = null;
    try
    {
      asFiles = System.IO.Directory.GetFiles(i_sPath, i_sBaseFilename + "_*.xml");
    }
    catch { return; }

    ms_dictCultureExceptionMessages.Clear();
    for (int ixFile = 0; ixFile < asFiles.Length; ixFile++)
    {
      string sXmlPathFilename = asFiles[ixFile];

      XmlDocument xmldoc = new XmlDocument();
      try
      {
        xmldoc.Load(sXmlPathFilename);
        XmlNode xmlnodeRoot = xmldoc.SelectSingleNode("/" + msc_sXmlGroup_Root);

        string sCulture = xmlnodeRoot.SelectSingleNode(msc_sXmlGroup_Info + "/" + msc_sXmlData_Culture).Value;
        CultureInfo oCultureInfo = new CultureInfo(sCulture);

        XmlNode xmlnodeMessages = xmlnodeRoot.SelectSingleNode(msc_sXmlGroup_Messages);
        XmlNodeList xmlnodelistMessage = xmlnodeMessages.ChildNodes;
        Dictionary<string, string> dictExceptionMessage = new Dictionary<string, string>(xmlnodelistMessage.Count + 10);
        for (int ixNode = 0; ixNode < xmlnodelistMessage.Count; ixNode++)
          dictExceptionMessage.Add(xmlnodelistMessage[ixNode].Name, xmlnodelistMessage[ixNode].InnerText);
        ms_dictCultureExceptionMessages.Add(oCultureInfo, dictExceptionMessage);
      }
      catch
      { return; }
    }
  }

  //----------------------------------------------------------------------------
  // SaveMessagesToXML
  //----------------------------------------------------------------------------
  public static void SaveMessagesToXML(string i_sPath, string i_sBaseFilename)
  {
    if (i_sBaseFilename == null) i_sBaseFilename = msc_sBaseFilename;

    foreach (KeyValuePair<CultureInfo, Dictionary<string, string>> kvpCultureExceptionMessages in ms_dictCultureExceptionMessages)
    {
      string sXmlPathFilename = i_sPath + i_sBaseFilename + "_" + kvpCultureExceptionMessages.Key.TwoLetterISOLanguageName + ".xml";
      Dictionary<string, string> dictExceptionMessage = kvpCultureExceptionMessages.Value;

      XmlDocument xmldoc = new XmlDocument();
      XmlWriter xmlwriter = null;
      XmlWriterSettings writerSettings = new XmlWriterSettings();
      writerSettings.Indent = true;

      try
      {
        XmlNode xmlnodeRoot = xmldoc.CreateElement(msc_sXmlGroup_Root);
        xmldoc.AppendChild(xmlnodeRoot);
        XmlNode xmlnodeInfo = xmldoc.CreateElement(msc_sXmlGroup_Info);
        XmlNode xmlnodeMessages = xmldoc.CreateElement(msc_sXmlGroup_Messages);
        xmlnodeRoot.AppendChild(xmlnodeInfo);
        xmlnodeRoot.AppendChild(xmlnodeMessages);

        XmlNode xmlnodeCulture = xmldoc.CreateElement(msc_sXmlData_Culture);
        xmlnodeCulture.InnerText = kvpCultureExceptionMessages.Key.Name;
        xmlnodeInfo.AppendChild(xmlnodeCulture);

        foreach (KeyValuePair<string, string> kvpExceptionMessage in dictExceptionMessage)
        {
          XmlNode xmlnodeMsg = xmldoc.CreateElement(kvpExceptionMessage.Key);
          xmlnodeMsg.InnerText = kvpExceptionMessage.Value;
          xmlnodeMessages.AppendChild(xmlnodeMsg);
        }

        xmlwriter = XmlWriter.Create(sXmlPathFilename, writerSettings);
        xmldoc.WriteTo(xmlwriter);
      }
      catch (Exception e)
      { return; }
      finally
      { if (xmlwriter != null) xmlwriter.Close(); }
    }
  }

  //----------------------------------------------------------------------------
  // CreateMessagesInThread
  //----------------------------------------------------------------------------
  private static void CreateMessagesInThread()
  {
    Thread.CurrentThread.Name = "CException.CreateMessagesInThread";

    Dictionary<string, string> dictExceptionMessage = new Dictionary<string, string>(0x1000);

    GetExceptionMessages(dictExceptionMessage);
    GetExceptionMessagesWin32(dictExceptionMessage);

    ms_dictCultureExceptionMessages.Add(Thread.CurrentThread.CurrentUICulture, dictExceptionMessage);
  }

  //----------------------------------------------------------------------------
  // GetExceptionTypes
  //----------------------------------------------------------------------------
  private static List<Type> GetExceptionTypes()
  {
    Assembly[] aoAssembly = AppDomain.CurrentDomain.GetAssemblies();

    List<Type> listoExceptionType = new List<Type>();

    Type oExceptionType = typeof(Exception);
    for (int ixAssm = 0; ixAssm < aoAssembly.Length; ixAssm++)
    {
      if (!aoAssembly[ixAssm].GlobalAssemblyCache) continue;
      Type[] aoType = aoAssembly[ixAssm].GetTypes();
      for (int ixType = 0; ixType < aoType.Length; ixType++)
      {
        if (aoType[ixType].IsSubclassOf(oExceptionType))
          listoExceptionType.Add(aoType[ixType]);
      }
    }

    return listoExceptionType;
  }

  //----------------------------------------------------------------------------
  // GetExceptionMessages
  //----------------------------------------------------------------------------
  private static void GetExceptionMessages(Dictionary<string, string> i_dictExceptionMessage)
  {
    List<Type> listoExceptionType = GetExceptionTypes();
    for (int ixException = 0; ixException < listoExceptionType.Count; ixException++)
    {
      Type oExceptionType = listoExceptionType[ixException];
      string sExceptionName = MakeXMLCompliant(oExceptionType.FullName);
      try
      {
        if (i_dictExceptionMessage.ContainsKey(sExceptionName))
          continue;
        Exception e = (Exception)(Activator.CreateInstance(oExceptionType));
        i_dictExceptionMessage.Add(sExceptionName, e.Message);
      }
      catch (Exception)
      { i_dictExceptionMessage.Add(sExceptionName, null); }
    }
  }

  //----------------------------------------------------------------------------
  // GetExceptionMessagesWin32
  //----------------------------------------------------------------------------
  private static void GetExceptionMessagesWin32(Dictionary<string, string> i_dictExceptionMessage)
  {
    string sTypeName = MakeXMLCompliant(typeof(Win32Exception).FullName) + "_";
    for (int iError = 0; iError < 0x4000; iError++)  // Win32 errors may range from 0 to 0xFFFF
    {
      Exception e = new Win32Exception(iError);
      if (!e.Message.StartsWith("Unknown error (", StringComparison.OrdinalIgnoreCase))
        i_dictExceptionMessage.Add(sTypeName + iError, e.Message);
    }
  }

  //----------------------------------------------------------------------------
  // CreateMessage
  //----------------------------------------------------------------------------
  private static string CreateMessage(Exception i_oException, CultureInfo i_oCultureInfo)
  {
    CException oEx = new CException(i_oException, i_oCultureInfo);
    Thread oTH = new Thread(new ParameterizedThreadStart(CreateMessageInThread));
    oTH.Start(oEx);
    while (oTH.IsAlive)
    { Thread.Sleep(10); }
    return oEx.m_sMessage;
  }

  //----------------------------------------------------------------------------
  // CreateMessageInThread
  //----------------------------------------------------------------------------
  private static void CreateMessageInThread(Object i_oData)
  {
    if (i_oData == null) return;
    CException oEx = (CException)i_oData;
    if (oEx.m_oException == null) return;

    Thread.CurrentThread.CurrentUICulture = oEx.m_oCultureInfo == null ? CultureInfo.InvariantCulture : oEx.m_oCultureInfo;
    // create new exception in desired culture
    Exception e = null;
    Win32Exception oWin32Exception = (Win32Exception)(oEx.m_oException);
    if (oWin32Exception != null)
      e = new Win32Exception(oWin32Exception.NativeErrorCode);
    else
    {
      try
      {
        e = (Exception)(Activator.CreateInstance(oEx.m_oException.GetType()));
      }
      catch { }
    }
    if (e != null)
      oEx.m_sMessage = e.Message;
  }

  //----------------------------------------------------------------------------
  // MakeXMLCompliant
  // from https://www.w3.org/TR/xml/
  //----------------------------------------------------------------------------
  private static string MakeXMLCompliant(string i_sName)
  {
    if (string.IsNullOrEmpty(i_sName))
      return "_";

    System.Text.StringBuilder oSB = new System.Text.StringBuilder();
    for (int ixChar = 0; ixChar < (i_sName == null ? 0 : i_sName.Length); ixChar++)
    {
      char character = i_sName[ixChar];
      if (IsXmlNodeNameCharacterValid(ixChar, character))
        oSB.Append(character);
    }
    if (oSB.Length <= 0)
      oSB.Append("_");
    return oSB.ToString();
  }

  //----------------------------------------------------------------------------
  private static bool IsXmlNodeNameCharacterValid(int i_ixPos, char i_character)
  {
    if (i_character == ':') return true;
    if (i_character == '_') return true;
    if (i_character >= 'A' && i_character <= 'Z') return true;
    if (i_character >= 'a' && i_character <= 'z') return true;
    if (i_character >= 0x00C0 && i_character <= 0x00D6) return true;
    if (i_character >= 0x00D8 && i_character <= 0x00F6) return true;
    if (i_character >= 0x00F8 && i_character <= 0x02FF) return true;
    if (i_character >= 0x0370 && i_character <= 0x037D) return true;
    if (i_character >= 0x037F && i_character <= 0x1FFF) return true;
    if (i_character >= 0x200C && i_character <= 0x200D) return true;
    if (i_character >= 0x2070 && i_character <= 0x218F) return true;
    if (i_character >= 0x2C00 && i_character <= 0x2FEF) return true;
    if (i_character >= 0x3001 && i_character <= 0xD7FF) return true;
    if (i_character >= 0xF900 && i_character <= 0xFDCF) return true;
    if (i_character >= 0xFDF0 && i_character <= 0xFFFD) return true;
    // if (i_character >= 0x10000 && i_character <= 0xEFFFF) return true;

    if (i_ixPos > 0)
    {
      if (i_character == '-') return true;
      if (i_character == '.') return true;
      if (i_character >= '0' && i_character <= '9') return true;
      if (i_character == 0xB7) return true;
      if (i_character >= 0x0300 && i_character <= 0x036F) return true;
      if (i_character >= 0x203F && i_character <= 0x2040) return true;
    }
    return false;
  }

  private static string msc_sBaseFilename = "exception_messages";
  private static string msc_sXmlGroup_Root = "exception_messages";
  private static string msc_sXmlGroup_Info = "info";
  private static string msc_sXmlGroup_Messages = "messages";
  private static string msc_sXmlData_Culture = "culture";

  private Exception m_oException;
  private CultureInfo m_oCultureInfo;
  private string m_sMessage;

  static Dictionary<CultureInfo, Dictionary<string, string>> ms_dictCultureExceptionMessages = new Dictionary<CultureInfo, Dictionary<string, string>>();
}

internal class Program
{
  public static void Main()
  {
    CException.CreateMessages(null);
    CException.SaveMessagesToXML(@"d:\temp\", "emsg");
    CException.LoadMessagesFromXML(@"d:\temp\", "emsg");
  }
}

1
यह UI की भाषा को Thread.CurrentUICulture भी बदल देता है, जिससे यह एक भयानक विकल्प बन जाता है। एक उत्कृष्ट उदाहरण संदेश बॉक्स पर हां / नहीं / ठीक / रद्द करें बटन हैं।
Nyerguds

0

अपवाद संदेश अंग्रेजी में

try
{
    ......
}
catch (Exception ex)
{
      throw new UserFriendlyException(L("ExceptionmessagesinEnglish"));
}

फिर स्थानीयकरण फ़ोल्डर पर जाएं और इसे प्रोजेक्टनाम में रखें। xml और जोड़ें

<text name="ExceptionmessagesinEnglish">Exception Message in English</text>

-1

आपको केवल त्रुटि संदेश (IIRC, सरल अपवाद के बजाय कॉल स्टैक लॉग करना चाहिए। String () को आपके लिए ऐसा करना चाहिए)। वहां से, आप यह निर्धारित कर सकते हैं कि अपवाद कहां से उत्पन्न हुआ है, और आमतौर पर यह अपवाद है कि यह कौन सा अपवाद है।


3
हम संदेश और स्टैकट्रेस लॉग कर रहे हैं। यदि संदेश स्पष्ट है तो यह बहुत आसान है।
कार्रा

-1

एक्सटेंशन विधि का उपयोग करके कैच ब्लॉक में अपवाद संदेश को ओवरराइड करें, फेंका गया संदेश कोड से है या नीचे वर्णित नहीं है।

    public static string GetEnglishMessageAndStackTrace(this Exception ex)
    {
        CultureInfo currentCulture = Thread.CurrentThread.CurrentUICulture;
        try
        {

            dynamic exceptionInstanceLocal = System.Activator.CreateInstance(ex.GetType());
            string str;
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");

            if (ex.Message == exceptionInstanceLocal.Message)
            {
                dynamic exceptionInstanceENG = System.Activator.CreateInstance(ex.GetType());

                str = exceptionInstanceENG.ToString() + ex.StackTrace;

            }
            else
            {
                str = ex.ToString();
            }
            Thread.CurrentThread.CurrentUICulture = currentCulture;

            return str;

        }
        catch (Exception)
        {
            Thread.CurrentThread.CurrentUICulture = currentCulture;

            return ex.ToString();
        }

1
जैसा कि मैंने पहले भी कहा ... InvalidOperationException। मजे की बात यह है कि संदेश के बिना इसका क्या मतलब है। एक नया उदाहरण जादुई रूप से नहीं होगा।
Nyerguds

-1

लॉगिंग उद्देश्यों के लिए, कुछ अनुप्रयोगों को अंग्रेजी अपवाद संदेश प्राप्त करना पड़ सकता है (सामान्य ग्राहक के UICulture में प्रदर्शित करने के अलावा)।

उस उद्देश्य के लिए, निम्न कोड

  1. वर्तमान UICulture को बदलता है
  2. "GetType ()" और "Activator.CreateInstance (t)" का उपयोग करके फेंकी गई अपवाद वस्तु को पुनः बनाता है
  3. नई UICuture में नई अपवाद वस्तु का संदेश प्रदर्शित करता है
  4. और फिर अंत में वर्तमान UICulture को पहले UICulture में बदल देता है।

        try
        {
            int[] a = { 3, 6 };
            Console.WriteLine(a[3]); //Throws index out of bounds exception
    
            System.IO.StreamReader sr = new System.IO.StreamReader(@"c:\does-not-exist"); // throws file not found exception
            throw new System.IO.IOException();
    
        }
        catch (Exception ex)
        {
    
            Console.WriteLine(ex.Message);
            Type t = ex.GetType();
    
            CultureInfo CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
    
            System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
    
            object o = Activator.CreateInstance(t);
    
            System.Threading.Thread.CurrentThread.CurrentUICulture = CurrentUICulture; // Changing the UICulture back to earlier culture
    
    
            Console.WriteLine(((Exception)o).Message.ToString());
            Console.ReadLine();
    
         }

1
यह गारंटी नहीं देता है कि नई ऑब्जेक्ट का अपवाद संदेश वही है जो फेंके गए अपवाद में है। यह पूरी तरह से अलग हो सकता है, और आमतौर पर यह पूरी तरह से अलग है। इसलिए हमें अपवाद संदेश की आवश्यकता है।
कृत्रिम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.