SharePoint Alfresco PHP MySQL
О сайте Контакты
пятница, 23 сентября 2011 г.

Проблемы с кодировками при русификации Project.NET и их решение

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

Неверная кодировка в отчетах XML

При генерации отчета XML, например, при экспорте в формат MSP, может возникнуть путаница кодировок кириллицы. Проблема решается просто, в параметрах запуска виртуальной машины Java необходимо явно определить кодировку: -Dfile.encoding=UTF8

Никаких правок кода PNET в данном случае делать не нужно.

Неверная кодировка в отчетах PDF

При экспорте диаграмм Гантта в получаемых PDF графики отображаются с неверными подписями к осям координат. Также «портятся» все остальные кириллические тексты в отчетах PDF. Данная проблема уже глубже и для ее решения необходимо скачать исходные коды Project.NET и модуля Itext. Интересен факт, что в PNET используется Itext 1.5.2, то есть одна из самых старых версий. Ее исходные коды в сети найти практически невозможно, однако есть исходный код версии Itext 2.1.7. Экспериментально установлена совместимость данной версии Itext с PNET, с незначительными оговорками (о которых ниже).

Чтобы исправить экспорт диаграмм Гантта, нужно редактировать файл GanttPDFServlet.java. Основные изменения требуется сделать в функциях:

createDataset(Iterator schedule)

createChart(final IntervalCategoryDataset dataset)

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

private String convertEncoding( String in ) {
  String out = "";
  
  char[] cArray = in.toCharArray();
  StringBuilder b = new StringBuilder();

    for (char c : cArray)
      if( 192 <= c && c <= 255 )
        b.append( (char)((int)c + 848) );
          else
        b.append( c );
      
    out = b.toString();   
  return out;
}

Иначе кириллические буквы будут выводиться со смещением по таблице кодировки.

Кроме того, в модуле Itext используются шрифты, в которых просто отсутствуют русские буквы. То есть даже если правильно написать код, буквы все равно не выведутся на экран, сопоставитель шрифтов о них не знает. Чтобы их добавить, необходимо сгенерировать файлы шрифтов awt с русскими буквами. Это можно сделать несколькими способами: с помощью утилиты ttf2pt1, с помощью многочисленный онлайн-инструментов (http://onlinefontconverter.com/ и другие), скачать готовые файлы awt.

Суть файлов awt в том, что там хранится информация о шрифте: ширине и границах букв, сопоставлении кода и буквы. По умолчанию в Itext используется шрифт Helvetica, который является коммерческим продуктом и не установлен на большинстве машин. Его заменяет Arial, поэтому генерацию русскоязычных символов можно производить из Arial. Следует отметить, что символы кириллицы лежат в диапазоне от 192 до 255 и от 1040 до 1103. Например, буква А – это 192-й символ с кодом afii10017. Она же – 1040-й символ. Символы с кодами типа uni0410 Itext обрабатывает некорректно, поэтому нужно указывать только afiiXXXXX. Символы кириллицы необходимо добавить в файлы Helvetica-Bold.afm и Helvetica.afm, так как это наиболее часто используемые в отчетах шрифты.

Также необходимо поработать с исходными кодами модуля Itext. Дело в том, что в нем по умолчанию прописана кодировка CP1252, которую нельзя изменить, кроме как правкой исходных кодов. Разумеется, при вызове шрифтов из программы можно указать совершенно любой шрифт, но PNET использует шрифты по умолчанию, в этом и загвоздка.

В функции getCalculatedBaseFont(boolean specialEncoding) необходимо прописать:

String fontName = BaseFont.HELVETICA;

String encoding = "Cp1251";

Собирать PNET и Itext разработчики рекомендуют на Java 1.5. Кстати, интересная особенность Itext: в версии 1.5.2 есть функции, которые отсутствуют в 2.1.7, то есть разработчики перестали их поддерживать. А PNET эти функции использует. Следовательно, при вызове этих функций будет появляться ошибка, по которой можно установить недостающую функцию и поставить на нее заглушку в исходниках Itext.

После всех этих манипуляций в отчетах PDF появятся кириллические буквы.

Неверная кодировка во вложениях уведомлений по email

Примером может послужить уведомление при назначении задачи пользователю. Сотрудник получает письмо, в котором имеется вложение в виде события календаря Outlook, чтобы он мог добавить его себе в календарь как напоминание. Однако этот вложенный файл содержит неверную кодировку и русские буквы отображаются вопросиками (?). Чтобы этого не происходило, необходимо поправить файл StringAttachment.java в исходных кодах PNET:

if (charset == null) {
    setDataSource(new ByteArrayDataSource(stringData, contentType, "UTF-8"));
} else {
    setDataSource(new ByteArrayDataSource(stringData, contentType, charset));
}

То есть добавить кодировку по умолчанию "UTF-8", иначе программа будет использовать CP1252.

При сохранении файла имя файла отображается в неверной кодировке

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

Sergey Lysenko, пятница, 23 сентября 2011 г.

Комментарии: