Есть такая замечательная вещь как gettext. Те, кто делал хоть раз многоязычный сайт, чувствовали, как неприятно использовать языковые константы и/или дублировать шаблоны.
Так вот от всего этого может избавить gettext.
Итак, что же это за зверь такой.
(далее я буду пояснять материал с http://www.onlamp.com/pub/a/php/2002/06/13/php.html)
Представим себе английскую версию (не вникая в код – о нем речь пойдет дальше) вот такого простого скрипта.
// I18N support information here
$language = 'en';
putenv("LANG=$language");
setlocale(LC_ALL, $language);
// Set the text domain as 'messages'
$domain = 'messages';
bindtextdomain($domain, "./locale");
textdomain($domain);
echo gettext("A string to be translated would go here");
?>
Явно видно что используется некий текст, который в многоязычной версии должен переводиться.
Почему не константы? А потому, что такой текст намного приятнее читается. Можно даже заменить последнюю строку на вот такое:
для краткости.
И насколько удобнее было бы если для смены языковой версии понадобится всего-лишь в $language = 'en'; установить 'ru'.
Итак, как же мы можем это все перевести.
В консоли введем
И получим на выходе файл-исходник для перевода – messages.po. Скачав утилиту poedit мы можем приступить к переводу – благо все ясно и понятно. Потом, когда перевод завершен, нужно выполнить
и мы получим скомпилированную версию, готовую к употреблению, которую ложим в locale/
И теперь при $language = 'ru'; gettext попытается взять locale/ru/LC_MESSAGES/messages.mo. Если же не найдет его – текст останется оригинальный. Что весьма удобно.
Примечание: у меня использовалась локаль ‘ru_RU.utf8′ и посему файлики ложил в locale/ru_RU/LC_MESSAGES/messages.mo. Список локалей можно получить командой
а добавить новую -
, где localename – одна из перечисленных в /usr/share/i18n/SUPPORTED.
Smarty
А теперь о том как это связать со Смарти.
Пост на форуме смарти показал приятный на вид и в реализации метод:
и реализацию метода:
$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]);
}
}
Что показалось мне довольно простым.
Однако, я не смог распарсить xgettext-ом шаблоны, и был вынужден прибегнуть к записи в откомпилированный шаблон вызова gettext-а, что я сделал через postfilter и измененную замену:
if($matches[2])
$txt = str_replace('"', '\"', $matches[2]);
if ($matches[1] != '') {
return "<?php echo dgettext(\"$matches[1]\", \"$txt\");?>";
} else {
return "<?php echo _(\"$txt\");?>";
}
}
и теперь пройдясь вдоль и поперек по сайту сгенерятся скомпилированные шаблоны смарти и из них gettext выцепит все наши строки.
Внимание, вопрос:
Как обойти такой некрасивый метод и заставить gettext съесть эти строки прямо в виде [[string to translate]]?
А почему нельзя использовать дополнительно функцию перевода с тэгами {t}translate me{/t}? Дописать в плагины отдельно и всё.
Артём Курапов
July 18th, 2007
Вообще субъективно приятнее [[text]] чем {t}text{/t}.
Но вопрос в том, как xgettext натравить на любой из этих вариантов
dm
July 19th, 2007
А я другого не понимаю – почему не воспользоваться config_load, что уже встроено в смарти и не юзать ленг файлы разные для разных языков?
anycolor
July 19th, 2007
А потому, что не хочется возвращаться к тому как было когда-то:
<h2>{PAGE_XXX_NAME}</h2>
<input type=text value={LOGIN_INPUT} />
dm
July 19th, 2007
dm: в случае с {t}text{/t} никакой xgettext не нужен. Это уже решается стандартными средствами Smarty. Код для блока {t} лежал на Smarty wiki еще год назад, а сейчас я его найти не смог, только ссылка осталась…
Вот что удалось найти по кускам кода:
https://oss.gonicus.de/labs/gosa/browser/trunk/...
Предупреждаю, что оно пытается само переводить с помощью babelfish. Лично я это безобразие сразу же отключил
y0prst
July 20th, 2007
О!!! Вот это самое оно. Только заменить бы как-то {t} на [[.
dm
July 21st, 2007
А я так и не смог заставить под Убунту xgettext создавать po файлы =
А вообще была мысль использовать {$text|gettext} модификатор.
akira
July 24th, 2007
Вот на форуме phpclub.ru нашел такое:
by Profic
dm
August 6th, 2007
A jesli dostupa k PHP net i Gettext ne vklu4en? Polu4ajetsa nichego rabotat’ ne budet? config_load – hot’ i nekrasivo, i staro, no nadezhno..
Zoltan
May 20th, 2008
А для этого, тов. Zoltan, обзаводимся своими серверами на которых можно поднять хоть черта лысого. Шаред хостинг – решение для начинающих, арендовать сервер (да хоть и виртуальный) уже совершенно не проблематично.
dm
May 20th, 2008