Исключительные сообщения на английском? - PullRequest
277 голосов
/ 16 октября 2008

Мы регистрируем любые исключения, которые происходят в нашей системе, записывая сообщение Exception.Message в файл Однако они написаны в культуре клиента. И турецкие ошибки не имеют большого значения для меня.

Так, как мы можем регистрировать любые сообщения об ошибках на английском языке, не изменяя культуру пользователей?

Ответы [ 15 ]

65 голосов
/ 29 сентября 2010

Вы можете найти оригинальное сообщение об исключении на unlocalize.com

62 голосов
/ 16 октября 2008

Эта проблема может быть частично решена. Код исключения Framework загружает сообщения об ошибках из своих ресурсов в зависимости от текущей локали потока. В случае некоторых исключений это происходит во время обращения к свойству Message.

За этими исключениями вы можете получить полную версию сообщения на английском и американском языках, кратко переключив языковой стандарт потока на 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»). В этих случаях сообщение все равно будет отображаться (частично) локализованным даже при использовании вышеуказанного кода.

Кроме использования непрактичных хаков, таких как запуск всего кода, не относящегося к пользовательскому интерфейсу, в потоке с локализацией en-US, для начала, кажется, с этим мало что можно поделать: исключение .NET Framework В коде нет средств для переопределения локали сообщения об ошибке.

37 голосов
/ 25 июля 2013

Возможно, спорный момент, но вместо того, чтобы установить культуру на en-US, вы можете установить ее на Invariant. В культуре Invariant сообщения об ошибках на английском языке.

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

Он имеет преимущество в том, что не выглядит предвзятым, особенно для неамериканских англоязычных языков. (a.k.a. избегает грубых замечаний коллег)

10 голосов
/ 07 января 2011

В Windows должен быть установлен язык интерфейса, который вы хотите использовать. Если нет, то никак не может волшебным образом узнать, что такое переведенное сообщение.

В en-US windows 7 ultimate с установленным pt-PT следующий код:

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. Поскольку файлы французской культуры не установлены, по умолчанию используется язык Windows по умолчанию (установлен?).

9 голосов
/ 07 января 2016

Вот решение, которое не требует какого-либо кодирования и работает даже для текстов исключений, которые загружаются слишком рано, чтобы мы могли изменять их по коду (например, в mscorlib).

Это может быть не всегда применимо в каждом случае (это зависит от ваших настроек, так как вам нужно иметь возможность создавать файл .config помимо основного файла .exe), но это работает для меня. Итак, просто создайте app.config в dev (или [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.Xml, для версий между 1 и 999, на французском языке (культура установлена ​​в "fr") для сборка, которая ... не существует (произвольная версия 999).

Поэтому, когда CLR будет искать французские ресурсы для этих двух сборок (mscorlib и System.xml), он не найдет их и изящно переключится на английский. В зависимости от контекста и тестирования вы можете добавить другие сборки в эти перенаправления (сборки, содержащие локализованные ресурсы).

Конечно, я не думаю, что это поддерживается Microsoft, поэтому используйте на свой страх и риск. Что ж, в случае, если вы обнаружите проблему, вы можете просто удалить эту конфигурацию и проверить, что она не связана.

4 голосов
/ 26 августа 2011

Я знаю, что это старая тема, но я думаю, что мое решение может быть весьма уместным для любого, кто сталкивается с ним в веб-поиске:

В журнале исключений вы можете войти в ex.GetType.ToString, что позволит сохранить имя класса исключения. Я ожидаю, что имя класса должно быть независимым от языка и поэтому всегда будет представлено на английском языке (например, «System.FileNotFoundException»), хотя в настоящее время у меня нет доступа к системе иностранного языка, чтобы проверить идея.

Если вам действительно нужен текст сообщения об ошибке, вы можете создать словарь всех возможных имен классов исключений и их эквивалентных сообщений на любом языке, который вы предпочитаете, но для английского я думаю, что имя класса вполне подходит.

3 голосов
/ 28 апреля 2014

.NET Framework состоит из двух частей:

  1. .NET Framework сама по себе
  2. Языковые пакеты .NET Framework

Все тексты (например, сообщения об исключениях, ярлыки кнопок в MessageBox и т. Д.) Написаны на английском языке в самой платформе .NET. Языковые пакеты имеют локализованные тексты.

В зависимости от вашей конкретной ситуации решение может состоять в том, чтобы удалить языковые пакеты (то есть сказать клиенту сделать это). В этом случае тексты исключений будут на английском языке. Тем не менее, обратите внимание, что весь другой текст, предоставляемый платформой, будет также английским (например, надписи кнопок на MessageBox, сочетания клавиш для ApplicationCommands).

3 голосов
/ 19 декабря 2012

Настройка Thread.CurrentThread.CurrentUICulture будет использоваться для локализации исключений. Если вам нужны два вида исключений (одно для пользователя, другое для вас), вы можете использовать следующую функцию для перевода сообщения об исключении. Он ищет в ресурсах .NET-библиотеки оригинальный текст, чтобы получить ключ ресурса, а затем возвращает переведенное значение. Но есть один недостаток, который я пока не нашел хорошего решения: сообщения, содержащие {0} в ресурсах, не будут найдены. Если у кого-то есть хорошее решение, я был бы признателен.

public static string TranslateExceptionMessage(Exception E, CultureInfo targetCulture)
{
    try
    {
        Assembly a = E.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);
        foreach (DictionaryEntry item in rsOriginal)
            if (item.Value.ToString() == E.Message.ToString())
                return rsTranslated.GetString(item.Key.ToString(), false); // success

    }
    catch { }
    return E.Message; // failed (error or cause it's not intelligent enough to locale '{0}'-patterns
}
3 голосов
/ 16 января 2009
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;

Без РАБОТЫ.

Ткс:)

2 голосов
/ 16 октября 2008

Я хотел бы представить один из этих подходов:

1) Исключения читаются только вами, т. Е. Они не являются клиентской функцией, поэтому вы можете использовать жестко привязанные нелокальные строки, которые не изменятся при работе в турецком режиме.

2) Включите код ошибки, например. 0X00000001 с каждой ошибкой, чтобы вы могли легко найти ее в английской таблице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...