Сборка русской версии 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 чтобы он перечитал измененные модули.