Alex L. Demidov

another DevOps guy

Сборка русской версии Movable Type

Для сборки руссифицированной версии Movable Type нам опять понадобятся исходники из svn-репозитария. Делаем чекаут, как описано в предыдущей статье о работе с файлом перевода и прикладываем к полученным исходникам патч patch-rubuild.gz, который добавляет возможность сборки русской версии.

Следующим шагом вносим в исходники все необходимые изменения для поддержки русского языка:

  • patch-rudate41.gz — добавляет русский формат дат
  • patch-rudirify41.gz — добавляет русские символы в таблицы преобразования заголовков статей в имена файлов (в отличии от патча Алексея Тутубалина изменяется также и Javascript код, а преобразование русских символов в латиницу сделано в соответствии с ГОСТ 7.79-2000)
  • patch-nofollow.gz — добавляет поддержку тэга <noindex> необходимого для российских поисковиков (автор Алексей Тутубалин)
  • patch-monday-mt41.gz — делает первым днем недели в календаре понедельник (автор Алексей Тутубалин)

После внесения изменений в код и шаблоны осталось добавить собственно файл перевода lib/MT/L10N/ru.pm (перевод проекта movable-type.ru, либо мой, менее полный перевод), файл стилей mt-static/styles_ru.css и два HTML-файла — index.html.ru и readme.html.ru (они есть в репозитарии русской версии Movable Type на Google Code). Файл перевода необходимо обработать в соответствии с инструкциями в предыдущей статье. В завершении можно изменить некоторые настройки по умолчанию (часовой пояс, кодировки, ссылки на новости, портал и техподдержку) для собираемого пакета, отредактировав файл build/mt-dists/ru.mk.

Сделав все необходимые изменения выполняем сборку пакета MTOS:

env LANG=C ./build/exportmt.pl --local --pack=MTOS --lang=ru --prod

В результате выполнения данной команды получим два архива с русской версией Movable Type — MTOS-4.1-ru.tar.gz и MTOS-4.1-ru.zip.

Работа с файлом перевода Movable Type.

Совпадение, но через два дня после публикации последней статьи на тему руссификации Movable Type, вышел перевод от проекта movable-type.ru. В сравнении с моим переводом, он более полный, но делался, судя по всему, по французскому файлу трансляции от версии 4.0 и в нем отсутствует более 300 строк, а также полтора десятка строк остались на французском.

Для того, чтобы синхронизировать файл перевода с текущим релизом (а также будущими релизами) и добавить в него отсутствующие строки, нужен полный комплект исходников Movable Type из svn-репозитария — в них пристутствует набор скриптов для манипуляций с файлами переводов (для работы скриптов нужен perl и набор unix-утилит - shell, awk, find и т.д.). Сначала делаем чекаут исходников из репозитария:

svn co http://code.sixapart.com/svn/movabletype/latest mtos-latest

После выполнения данной команды в каталоге mtos-latest будет три подкаталога: dev, stable и release. Нам нужен подкаталог release, в котором находится последний релиз Movable Type с которым мы будем работать. Первым делом кладем наш файл перевода ru.pm в подкаталог lib/MT/L10N/. Следующим шагом запускаем собственно генерацию обновленного файла перевода из каталога release:

sh build/l10n/make-l10n ru

В результате работы данного скрипта в каталоге /tmp будет сгенерировано четыре файла:

  • ru-base.pm — файл со всеми строками трансляции (в том числе дублирующиеся строки)
  • ru-nodupe.pm — файл с удаленными дубликатами строк
  • ru-old.pm —строки трансляции которые более не используются
  • ru.pm —новый файл перевода

В новом файле перевода /tmp/ru.pm будут добавлены отсутствующие строки перевода (отмечены комментарием «Translate - New») и будут отчемены строки с регистром перевода отличающимся от оригинала — например, переводы следующего вида:

'video' => 'Видео'

Этот файл уже готов к использованию, но для полноценной поддержки русского языка я сделал дополнительный фильтр ru-filter.pl, через который надо пропустить файл перевода:

cat /tmp/ru.pm | perl ru-filter.pl > lib/MT/L10N/ru.pm

Данный фильтр делает следующее:

  • отмечает комментарием «# Translate - No translation» непереведенные строки, в которых оригинал и перевод совпадают
  • отмечает комментарием «# Translate - No russian char» строки перевода в которых не встречаются русские буквы
  • отключает строки с пустым переводом
  • добавляет perl’овый код для правильной поддержки множественного числа

Поддержка множественного числа сделана через переопределение функции quant из Locale::Maketext. Теперь второй и третий параметры этой функции принимают формы слова для значений числительного от 2 до 4 и от 5 до 0 соответственно. Таким образом можно писать «[quant, _1,минута,минуты,минут]» и соответствующий текст будет генерироваться как «1 минута, 2 минуты, 5 минут» вместо «1 минута, 2 минут., 3 минут.»

Руссификация Movable Type 4.1

Продолжаем работу с Movable Type. Руссификацию пришлось делать в два захода. На первом заходе, после предварительного гугленья, был применен рецепт для руссификации Movable Type версии 4 от Алексея Тутубалина с небольшими изменениями:

  • приложен патч patch-monday-mt41.gz для того чтобы в календаре неделя начиналась с понедельника
  • приложен патч patch-dirify.gz для конвертации русских символов в заголовках статей в латиницу при генерации имени файла
  • приложен патч patch-nofollow.gz для поддержки тэга <noindex> для Яндекса

Патч patch-rudate.gz не прикладывал, но посмотрев в него, сделал свой. Вместо того, чтобы использовать итальянский формат, добавил русский в список форматов, изменив lib/MT/Util.pm и tmpl/cms/cfg_entry.tmpl. Изменен также и формат отображения — вместо 24.03.2008 будет Март, 24 2008. Патч patch-rudate41.gz прилагается.

Далее последовал наиболее нудный этап — перевод шаблонов. Разбор со скриптом Алексея Тутубалина для экспорта/импорта шаблонов я оставил на потом (этот скрипт был сделан до выхода версии 4.1 и неизвестно как он с ней работает, к тому же он требует установки плугина TemplateInstaller), поэтому шаблоны перевел вручную через админку Movable Type. Хотя шаблонов около полусотни, но сами они немногословны и переводить можно не все, а только те, которые реально используются. Поэтому первые результаты появился сравнительно быстро, но в процессе перевода увлекся файн-тюнингом оформления и внес слишком много изменений в шаблоны, так что собравшись создавать блог для своей SO, обнаружил что мне надо либо вычищать свое оформление, либо возвращаться к стандартным шаблонам и переводить их опять с нуля.

Немного поразмышляв, решил выбрать другой подход. В Movable Type есть в наличии полная инфраструктура для локализации базирующаяся на perl’овом Locale::Maketext и документация рекомендуют именно этот подход. Проект movable-type.ru после выхода версии 4.0 в августе 2007 вроде бы огранизовал коллективную попытку сделать русский перевод и месяц назад даже заявлена 90% готовность, но реальных результатов пока не наблюдается. Конечно объем текста в более чем 4 тысячи строк на первый взгляд выглядит ужасающе, но ничто не мешает переводить текст по частям, например, для начала только те строки, которые используются в самих блогах, а не в админке.

За пару вечеров у меня был готов перевод следующих компонентов используемых в опубликованном блоге:

  • шаблоны default_templates/*.mtml которые используются при генерации шаблонов нового блога
  • шаблоны plugins/WidgetManager/default_widgets/*.mtml для widget’ов
  • php-скрипты динамической публикации

Все это занимает где-то чуть более 600 строк (ru-published-only.pm). Данный файл необходимо переименовать в ru.pm и положить в lib/MT/L10N/, при этом русский язык автоматически станет доступен для выбора в профиле пользователя. Стоит иметь в виду, что перевод фраз в шаблонах на русский производится в момент генерации шаблонов и только если у пользователя выбран русский язык в профиле. Если блог уже создан, то можно перегенерировать шаблоны заново, зайдя в своем блоге через меню «Design» → «Manage Templates» → «Refresh Blog Templates». При перегенерации большинство новых руссифицированных шаблонов будут иметь русские имена и у меня лично слетели Archive Maps и наборы widget’ов. Нужно будет их пересоздать, предварительно удалив все старые шаблоны и widget’ы.

Все остальное пока находится в процессе перевода, хотя наиболее часто используемые части админки уже переведены практически полностью (можно скачать Файл перевода). В качестве основы для этого файла взят es.pm, поэтому непереведенные строки будут по испански. Также добавлен скрипт mt_ru.js который содержит локализованные строки для JavaScript и локализованную таблицу для динамической dirtif’икации заголовков в имена файлов. Файл стилей styles_ru.css содержит одну строчку — модификация ширины колонок в виджете календаря.

По мере дальнейшего перевода я планирую выкладывать обновленную версию файла ru.pm, следите за обновлениями.

Ускорение Movable Types ( Apache и FastCGI )

После установки Movable Type обнаружилось что работа с его админкой (CMS) достаточно некомфортна из-за её существенной тормознутости — время загрузки главной страницы составляет около 15 секунд. Впрочем, это не удивительно, поскольку админка реализована как достаточно тяжелый perl’овый скрипт со множеством зависимостей которые при работе в режиме стандратного CGI подгружаются при каждом HTTP-запросе.

Первой мыслью было попробовать запустить его под mod_perl, который у меня уже есть, но как оказалось Movable Type поддерживает только mod_perl 1.x, а я уже третий год как переехал на Apache 2.x. Поэтому пришлось обратиться к альтернативном варианту — FastCGI, отличие которого от классического CGI именно в том, что скрипт обслуживает не один, а множество HTTP-запросов, чем минимизируются временные затраты на запуск и инициализацию скрипта.

Сначала обеспечиваем поддержку FastCGI в Apache — это делается с помощь модуля mod_fastcgi (или альтернативная реализация mod_fcgid). Ставим модуль и подключаем его в httpd.conf. настройки для mod_fastcgi:

LoadModule fastcgi_module libexec/apache22/mod_fastcgi.so
<IfModule mod_fastcgi.c>
  AddHandler fastcgi-script .fcgi
  FastCgiIpcDir /var/run/fcgidsock/
</IfModule>

настройки для mod_fcgid:

LoadModule fcgid_module libexec/apache22/mod_fcgid.so
<IfModule mod_fcgid.c>
  AddHandler fcgid-script .fcgi 
  SocketPath /var/run/fcgidsock/
</IfModule>

Сам Movable Type начиная с версии 4 поддерживает работу через FastCGI из коробки, поэтому для его настойки достаточно указать для каталога где находятся скрипты mt*.cgi следующую директиву:

AddHandler fcgid-script .cgi

или

AddHandler fastcgi-script .cgi

После включения данной опции тестирование с помощью ApacheBench показало на моей домашней машинке ускорение более чем на порядок — с 0.75 запросов в секунду до 15. Но особого ускорения при работе с админкой не прозошло. Налицо классический случай «premature optimization», которая «root of all evil» © C.A.R. Hoare.

Поэтому пришлось все-таки более внимательно посмотреть в YSlow и последовательно применить предлагаемые рекомендации. Основная проблема оказалась в большом количестве объектов на странице и как следствие, большом количестве HTTP запросов (около 50 в данном случае), причем большинство запросов были If-Modified-Since на файлы из mt-static, в осовном изображения. Лечиться это добавлением заголовков Expires для каталога mt-static с помощью mod_expires:

ExpiresActive On
ExpiresDefault "access plus 1 month"

С включением данной опции броузер перестал обращаться к каждой картинке при каждой загрузке страницы, что сократило количество запросов с полусотни до ровно одного — обращение собственно к mt.cgi. Общий объем передаваемых данных также сократился с 100Kb (уже с учетом включеной компрессии для text/*) до 10Kb. Общее же время загрузки страницы сократилось с 15 секунд до 5-6 секунд по таймеру YSlow и до 3-4 секунд по секундомеру с отключеным FireBug‘ом и YSlow.

Достигнутый результат меня вполне устроит и тему оптимизации можно отложить. Дальше нужно будет заниматься уже переводом на русский и переносом на боевой сервер в тесный jail. А пока в процессе первых дней эксплуатации выяснилось пара нюансов. Во-первых, не все скрипты MT работают в режиме FastCGI, поэтому лучше использовать следующие настройки подсмотренные в документации Movable Type:

<FilesMatch "^mt(?:-(?:comments|search|tb|view))?\.cgi$">
     AddHandler fcgid-script .cgi
</FilesMatch>

Во-вторых, процесс mt.cgi со временем может разрастаться до достаточно неприличиных размеров (более 100 Mb) и поэтому лучше настроить mod_fastcgi так, чтобы он переодические его перезапускал:

   FastCgiConfig -maxProcesses 10 -killInterval 3600

и для mod_fcgid

   ProcessLifeTime 3600
   MaxProcessCount 10
   MaxRequestsPerProcess 500

И в третьих, при работе через FastCGI возникают неудобства с изменением кода MT на ходу — необходимо постоянно перезапускать mt.cgi чтобы он перечитал измененные модули.

Продолжение следует