Сегодня у Lecacus'а на сайте наткнулся на упоминание одной нерешённой проблемы:
У меня не работают автоматические ссылки меток в содержимом записи для меток на русском языке. Т.е. если есть метка "wordpress", то слово "wordpress" заменяется на ссылку http://myblog.net/tag/wordpress/. А вот если есть метка "спорт", то слово "спорт" ссылкой не заменяется. Подскажите как сделать так, чтобы плагин работал и с русскими метками.
А так как сегодня мне уже пришлось иметь дело с Simple Tags, я решил разобраться, в чём же дело и исправить досадный баг.
Сам по себе код плагина довольно-таки простой (что определённо делает честь автору), но регулярные выражения, использованные в коде, требуют некоторых знаний и навыков.
За создание автоматических меток отвечает метод SimpleTags::autoLinkTags
, основу которого составляют регулярные выражения из PHP Markdown Михеля Фортина (Michel Fortin); замечу, что эти регулярные выражения исправлять не пришлось (хотя, по-хорошему, их можно упростить).
Сама ошибка находится в данной строке:
- $match = "/\b" . preg_quote($term_name, "/") . "\b/".$case;
Очень многие "Забугорные" программисты (а также наши, работающие на иностранцев), привыкли считать, что нет иной кодовой таблицы, нежели iso-8859-x, что, собственно, и выражается в регулярном выражении.
Те, кто знаком с PCRE, знают, что \b — это граница слова. Но в локали по умолчанию русские буквы не попадают в категорию "буквы"; как следствие, регулярное выражение /\bспорт\b/
не сработает.
Решение проблемы состоит в использовании классов символов Unicode (то, что знают, увы, очень немногие программисты).
Фактически, нужно было проверять на нахождение не-буквы перед меткой и после метки; например, так:
Уже лучше, но работает не всегда. В частности, не будет работать, если метка идет сразу после открывающего тэга, либо сразу перед закрывающим тэгом (не сработает условие (\PL) в начале или в конце). Правильным решением будет следующее:
Полное решение выглядит сложнее, но суть должна быть понятна.
Ниже приведён патч в формате unified diff:
+++ simple-tags.client.php 2008-11-22 07:53:15.000000000 +0200
@@ -262,8 +262,9 @@
foreach ( (array) $this->link_tags as $term_name => $term_link ) {
$filtered = ""; // will filter text token by token
- $match = "/\b" . preg_quote($term_name, "/") . "\b/".$case;
- $substitute = '<a href="'.$term_link.'" class="st_tag internal_tag" '.$rel.' title="'. attribute_escape( sprintf( __('Posts tagged with %s', 'simpletags'), $term_name ) )."\">
+ $quoted = preg_quote($term_name, "/");
+ $match = "/(\PL|\A)(" . preg_quote($term_name, "/") . ")(\PL|\Z)/u".$case;
+ $substitute = '$1<a href="'.$term_link.'" class="st_tag internal_tag" '.$rel.' title="'. attribute_escape( sprintf( __('Posts tagged with %s', 'simpletags'), $term_name ) )."\
// for efficiency only tokenize if forced to do so
if ( $must_tokenize ) {
Внимание: патч будет работать только если PHP собран с поддержкой UTF-8, если кодировка блога установлена в UTF-8 и соединение с базой данных тоже использует кодировку UTF-8. В принципе, ничего запредельного, нормальная инсталляция WordPress будет отвечать этим требованиям.
Те, кто не хотят заморачиваться с патчем, могут скачать пропатченную версию (но она требует как минимум WordPress 2.5).
Здравствуйте Владимир.
Написал на блоге Кактуса благодарность в вашу сторону и решил повторить здесь.
После установки пропатченного плагина сразу пошла линковка ru тегов, что и требовалось доказать.
Огромное спасибо за испраление бага. Очень хотелось подключить эту функцию.
Благодаря вам я реализовал это на своем сайте.
Еще раз СПАСИБО!
Михаил.
Михаил, всегда пожалуйста!
Будут вопросы — обращайтесь!
Огромное спасибо. Тоже долго с плагином мучался, пока блог Кактуса не почитал и сюда не попал.
Всегда пожалуйста. Будут пожелания — пишите.
у меня выдает
Warning: preg_match() [function.preg-match]: Compilation failed: PCRE does not support \L, \l, \N, \P, \p, \U, \u, or \X at offset 2 in /home/codeby/www/wp-content/plugins/simple-tags/2.5/simple-tags.client.php on line 288
Какая версия PHP?
PHP Version 5.2.4
Red Hat Linux, я полагаю?
Что говорит
phpinfo()
по поводу версии PCRE?Если есть shell, можно посмотреть так:
Полагаю, что версия будет меньше пятой (например, 4.5)?
PCRE Library Version 4.5 01-December-2003
Значит, я был прав… Увы, программно здесь ничего нельзя сделать: сборщик пакета PHP для Вашей операционной системы сделал непростительную тупость: он собрал новую версию PHP со старой библиотекой PCRE (самая последняя версия PCRE — 7.8 от 5 сентября 2008 года).
Если у Вас выделенный сервер, могу посоветовать только пересобрать PHP по-нормальному.
PS — поддержка Unicode добавлена в PCRE только в пятой версии.
вышла новая версия 1.6.1 с новыми улучшениями и исправлениями (для версии 2.7 пофиксили некоторые места).
в приведенном потче в последней “зеленой строке” в конце обрезано. это так к слову. просто решил новую версию исправить по методике и когда патчил заметил что тут недописана строка (несколько символов затерялось). исправил у себя сам и выложил обновленный архив плагина тут http://lecactus.ru/2007/10/07/851/