Posterous theme by Cory Watilo

Gettext and Smarty

Есть такая замечательная вещь как gettext. Те, кто делал хоть раз многоязычный сайт, чувствовали, как неприятно использовать языковые константы и/или дублировать шаблоны. Так вот от всего этого может избавить gettext. Итак, что же это за зверь такой. (далее я буду пояснять материал с http://www.onlamp.com/pub/a/php/2002/06/13/php.html) Представим себе английскую версию (не вникая в код - о нем речь пойдет дальше) вот такого простого скрипта. [cc lang="php"] [/cc] Явно видно что используется некий текст, который в многоязычной версии должен переводиться. Почему не константы? А потому, что такой текст намного приятнее читается. Можно даже заменить последнюю строку на вот такое: [cc lang="php"] echo _("A string to be translated would go here"); [/cc] для краткости. И насколько удобнее было бы если для смены языковой версии понадобится всего-лишь в $language = 'en'; установить 'ru'. Итак, как же мы можем это все перевести. В консоли введем [cc lang="bash"] xgettext -n *.php [/cc] И получим на выходе файл-исходник для перевода - messages.po. Скачав утилиту poedit мы можем приступить к переводу - благо все ясно и понятно. Потом, когда перевод завершен, нужно выполнить [cc lang="bash"] msgfmt messages.po [/cc] и мы получим скомпилированную версию, готовую к употреблению, которую ложим в locale//LC_MESSAGES/. И теперь при $language = 'ru'; gettext попытается взять locale/ru/LC_MESSAGES/messages.mo. Если же не найдет его - текст останется оригинальный. Что весьма удобно. Примечание: у меня использовалась локаль 'ru_RU.utf8' и посему файлики ложил в locale/ru_RU/LC_MESSAGES/messages.mo. Список локалей можно получить командой [cc code="bash"]locale -a[/cc] а добавить новую - [cc lang="bash"]locale-gen [/cc], где localename - одна из перечисленных в /usr/share/i18n/SUPPORTED.

Smarty

А теперь о том как это связать со Смарти. Пост на форуме смарти показал приятный на вид и в реализации метод: [cc lang="ini"] [[Text to be translated]] [/cc] и реализацию метода: [cc lang="php"] ... $smarty->register_prefilter('translate_template'); ... function translate_template($tpl_source, &$smarty) { return preg_replace_callback('/\[\[(?:([\w-_]+)\!)?(.*?)\]\]/', 'translate_template_item', $tpl_source); } function translate_template_item($matches) { if ($matches[1] != '') { return dgettext($matches[1], $matches[2]); } else { return gettext($matches[2]); } } [/cc] Что показалось мне довольно простым. Однако, я не смог распарсить xgettext-ом шаблоны, и был вынужден прибегнуть к записи в откомпилированный шаблон вызова gettext-а, что я сделал через postfilter и измененную замену: [cc lang="php"] function translate_template_item($matches) { if($matches[2]) $txt = str_replace('"', '\"', $matches[2]); if ($matches[1] != '') { return ""; } else { return ""; } } [/cc] и теперь пройдясь вдоль и поперек по сайту сгенерятся скомпилированные шаблоны смарти и из них gettext выцепит все наши строки. Внимание, вопрос: Как обойти такой некрасивый метод и заставить gettext съесть эти строки прямо в виде [[string to translate]]?
| Viewed
times
Filed under: