Как сделать exception message на русском?

Рейтинг: 2Ответов: 4Опубликовано: 05.05.2015

Студия 2015/2010 английская версия. Интересует именно возможность вывода сообщения на русском языке. Возможно вывод только определенной группы исключений ну это в прицепе не принципиально.

 try
 {
     //капец!!!
 }
 catch (Exception ex)
 {
     MessageBox.Show(ex.Message);
 }

Ответы

▲ 6Принят

Если вас интересуют сообщения в исключениях, которые генерирует .NET Frameowrk, то обратите внимание на свойство Thread.CurrentUICulture. Например, следующая программа:

Thread.CurrentThread.CurrentUICulture = new CultureInfo("ru-ru");
try {
    throw new InvalidOperationException();
}
catch (Exception e) {
    Console.WriteLine(e.Message);
}

Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-us");
try {
    throw new InvalidOperationException();
}
catch (Exception e) {
    Console.WriteLine(e.Message);
}

выведет следующий текст:

Операция является недопустимой из-за текущего состояния объекта.
Operation is not valid due to the current state of the object.

Текущая локаль по умолчанию берётся из настроек системы, то есть соответствует языку UI в Windows. Обычно менять это значение не следует, в этом случае пользователь видит текст на том языке, который предпочитает. Если ваше приложение многоязыковое, то вы можете менять локаль UI в зависимости от текущего языка в вашем приложении (а вот Thread.CurrentCulture лучше не трогать).

▲ 11

Исключения не предназначены для показа пользователю. Текст исключения не локализуем, содержит техническую информацию, содержит форматирование, интересное программисту, а не пользователю. Он может выдать секретную или приватную информацию, которую вы вовсе не планировали показывать пользователю. Самое ужасное — текст исключения не помогает пользователю выйти из проблемной ситуации, он лишь описывает непосредственную причину ошибки в терминах технических подробностей случившегося, а не в терминах того, что нужно на самом деле пользователю, и что он сделал не так (или что пошло не так).

Поэтому никогда (то есть действительно никогда) не выводите пользователю в UI текст исключения.

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

Например, если при чтении конфигурационного файла возникла ошибка, связанная с тем, что доступ к файлу запрещён, или что в файле не найдем валидный XML, или что значение "привет земляне" не может быть преобразовано к типу int и не может быть значением атрибута version.major — всё это неинтересно пользователю. Ваш код должен сказать, что инсталляция программы испорчена, и её нужно восстановить, или (ещё лучше!) проинформировать пользователя, что произведена успешная попытка сброса испорченной конфигурации программы.

Это должно выглядеть примерно так:

try
{
    await model.ApplySettings();
    return;
}
catch (InvalidSettingsException e)
{
    Logger.Log(e);
    // для старых версий .NET вам придётся вынести await за catch
    var corrected = await model.TryRepairSettings();
    if (corrected)
    {
        await PresentSettingsCorrected();
    }
    else
    {
        await PresentSettingsUncorrectable();
        throw new UnrecoverableSettingsError(e);
    }
}

Локализацией сообщения займётся процедура PresentSettingsCorrectedPresentSettingsUncorrectable) обычным образом, как и любая другая процедура, ответственная за взаимодействие с пользователем.

Код

try
{
    ...
}
catch (Exception e)
{
    MessageBox.Show(e.ToString());
}

— преступление. Никогда так не делайте. Программа, написанная так, всеми и всегда будет считаться студенческой поделкой.


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


(вынес из комментариев) Правильная реакция на ошибочные ситуации — очень важная задача, и притом непростая. Обычно при прототипировании приложения на обработке ошибок экономят время, потому что главное на этом этапе — показать функциональность, работающую «когда всё в порядке». Потом встраивание логики обработки ошибок становится сложнее, ведь она превращает линейное течение логики программы в разветвлённое.

На самом деле в UI-приложении экранов, обслуживающих ошибочные ситуации, может быть и столько же, сколько экранов для нормального течения программы! Поэтому на правильную обработку таких ситуаций придётся потратить время, сравнимое с временем разработки основной логики приложения.

К сожалению, часто этим пренебрегают даже крупные производители ПО, в результате чего мы и видим беспомощные сообщения об ошибках в стиле «Произошло что-то ужасное, я падаю» или «Вот вам текст исключения, разбирайтесь сами». Пользователи часто выносят своё мнение о программе по таким вот недоделкам. Которые, на мой вкус, и отличают хорошо, с любовью сделанный проект от закодированного на коленке прототипа.

▲ 3
  1. Надо ловить только те исключения, которые являются ожидаемыми.
  2. Надо логировать исключение целиком (а не только Message).
  3. Пользователю можно показывать какое-либо сообщение, а не Message.
  4. Если возникло неожиданное исключение, пользователю можно сообщить о неизвестной ошибке (при этом в логе всё равно должна быть полная информация).

PS: Если бы речь шла о программе для себя, вопрос о локализации информации об исключениях не возник бы, да?


Но программа простая отлавливать перечислять все возможны исключения не вижу смысла.

А должен видеть.

  1. Именно на основе типа исключения надо понимать, что пошло не так, что делать и что сообщать пользователю. Message вообще не обязательно содержит информацию об ошибке - например, полезная информация может содержаться во вложенном исключении.
  2. Отлов всех исключений не даёт даже нормально код при написании отлаживать. Я уже правил чей-то замечательный код, в котором охапка вызовов на пару сотен строк в сумме обёрнута в catch(Exception) с выводом "Ошибка открытия файлов", а я код редактирую, у меня там в рандомных местах ошибки.
  3. Для необработанных исключений следует использовать специальный хэндлер.

В любом случаи вопрос не про выводить/не выводить сообщения/когда выводить/логировать/не логировать, а про скажем так русификацию сообщения исключения.

Надо перехватывать конкретный тип исключения, по нему показывать соответствующее сообщение на нужном языке (которое не связано с Message).

Если предполагается, что пользователи будут продвинутыми, можно добавить кнопку для отображения подробной информации об исколючении, где уже вывести ex.ToString() (а не ex.Message).

▲ 2

У пользователя должен быть установлен языковой пакет для .Net Framework. Тогда все сообщения будут выводиться на русском.