Simple Tags и автоматические ссылки меток на русском языке

Добавляем поддержку многобайтных символов в Simple Tags

Сегодня у Lecacus’а на сайте наткнулся на упоминание одной нерешённой проблемы:

У меня не работают автоматические ссылки меток в содержимом записи для меток на русском языке. Т.е. если есть метка «», то слово «» заменяется на ссылку http://myblog.net/tag/wordpress/. А вот если есть метка «спорт», то слово «спорт» ссылкой не заменяется. Подскажите как сделать так, чтобы работал и с русскими метками.

А так как сегодня мне уже пришлось иметь дело с , я решил разобраться, в чём же дело и исправить досадный баг.

Сам по себе код плагина довольно-таки простой (что определённо делает честь автору), но регулярные выражения, использованные в коде, требуют некоторых знаний и навыков.

За создание автоматических меток отвечает метод SimpleTags::autoLinkTags, основу которого составляют регулярные выражения из Markdown Михеля Фортина (Michel Fortin); замечу, что эти регулярные выражения исправлять не пришлось (хотя, по-хорошему, их можно упростить).

Сама находится в данной строке:

[-]
View Code PHP
  1. $match = "/\b" . preg_quote($term_name, "/") . "\b/".$case;

Очень многие “Забугорные” программисты (а также наши, работающие на иностранцев), привыкли считать, что нет иной кодовой таблицы, нежели iso-8859-x, что, собственно, и выражается в регулярном выражении.

Те, кто знаком с PCRE, знают, что \b — это граница слова. Но в локали по умолчанию русские буквы не попадают в категорию “буквы”; как следствие, регулярное выражение /\bспорт\b/ не сработает.

Решение проблемы состоит в использовании классов символов Unicode (то, что знают, увы, очень немногие программисты).

Фактически, нужно было проверять на нахождение не-буквы перед меткой и после метки; например, так:

[-]
View Code PHP
$match = "/(\PL)(" . preg_quote($term_name, "/") . ")(\PL)/u".$case;

Уже лучше, но работает не всегда. В частности, не будет работать, если метка идет сразу после открывающего тэга, либо сразу перед закрывающим тэгом (не сработает условие (\PL) в начале или в конце). Правильным решением будет следующее:

[-]
View Code PHP
$match = "/(\PL|\A)(" . preg_quote($term_name, "/") . ")(\PL|\Z)/u".$case;

Полное решение выглядит сложнее, но суть должна быть понятна.

Ниже приведён в формате unified diff:

--- simple-tags.client.php.orig 2008-11-22 06:15:22.000000000 +0200
+++ 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 ) )."\">$0</a>";
                $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 ) )."\">$2</a>$3";
 
                                // for efficiency only tokenize if forced to do so
                                if ( $must_tokenize ) {

Внимание: будет работать только если собран с поддержкой UTF-8, если кодировка блога установлена в UTF-8 и соединение с базой данных тоже использует кодировку UTF-8. В принципе, ничего запредельного, нормальная инсталляция будет отвечать этим требованиям.

Те, кто не хотят заморачиваться с патчем, могут скачать пропатченную версию (но она требует как минимум  2.5).

Скачать Simple Tags 1.5.7.1.

Добавить в закладки

Связанные записи

Автор: Vladimir; опубликовано в: Патчи; метки: PHP, Simple Tags, utf8, WordPress, ошибка, патч, плагин
22
Ноя
2008

RSS Комментарии к статье «Simple Tags и автоматические ссылки меток на русском языке» (17)  »

  1. Михаил

    Здравствуйте Владимир.
    Написал на блоге Кактуса благодарность в вашу сторону и решил повторить здесь.
    После установки пропатченного плагина сразу пошла линковка ru тегов, что и требовалось доказать.
    Огромное спасибо за испраление бага. Очень хотелось подключить эту функцию.
    Благодаря вам я реализовал это на своем сайте.
    Еще раз СПАСИБО!
    Михаил.

  2. Михаил, всегда пожалуйста! :-)

    Будут вопросы — обращайтесь!

  3. Огромное спасибо. Тоже долго с плагином мучался, пока блог Кактуса не почитал и сюда не попал.

  4. у меня выдает

    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?

        • Red Hat Linux, я полагаю?

          Что говорит phpinfo() по поводу версии PCRE?

          Если есть shell, можно посмотреть так:

          [-]
          View Code Bash
          php -i | grep "PCRE Library Version"

          Полагаю, что версия будет меньше пятой (например, 4.5)?

          • PCRE Library Version 4.5 01-December-2003

          • Значит, я был прав… Увы, программно здесь ничего нельзя сделать: сборщик пакета PHP для Вашей операционной системы сделал непростительную тупость: он собрал новую версию PHP со старой библиотекой PCRE (самая последняя версия PCRE — 7.8 от 5 сентября 2008 года).

            Если у Вас выделенный сервер, могу посоветовать только пересобрать PHP по-нормальному.

            PS — поддержка Unicode добавлена в PCRE только в пятой версии.

  5. вышла новая версия 1.6.1 с новыми улучшениями и исправлениями (для версии 2.7 пофиксили некоторые места).
    в приведенном потче в последней “зеленой строке” в конце обрезано. это так к слову. просто решил новую версию исправить по методике и когда патчил заметил что тут недописана строка (несколько символов затерялось). исправил у себя сам и выложил обновленный архив плагина тут http://lecactus.ru/2007/10/07/851/

  6. Me

    Добрый день Владимир
    Может ли ваш плагин файл кэш корректно работать с большим кол-вом комментов как у меня на сайте? WP Hyper кэш увы не спправляется и комменты обновляются только в еденицу времени.

  7. Me

    Все просто- этот плагин работает так же отлично как File Cash
    Думаю это отличная замена стандартным модулям WP вроде Hyper Cash

  8. [...] назад я рассказывал о том, что Simple Tags не умеет работать с многобайтовыми символами (коими, к слову, являются русские буквы в кодировке [...]

  9. [...] вышла очередная версия плагина Simple Tags. Проблема с UTF-8/многобайтными строками осталась (нужно бы написать автору ещё раз). Вдобавок [...]

Оставить комментарий к записи «Simple Tags и автоматические ссылки меток на русском языке»

Вы можете использовать данные тэги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Изображения должны быть включены!

Оставляя комментарий, вы выражаете своё согласие с Правилами комментирования.

Подписаться, не комментируя