Как я могу генерировать URL-слагов в Perl? - PullRequest
5 голосов
/ 24 октября 2010

Веб-фреймворки, такие как Rails и Django, имеют встроенную поддержку «слагов», которые используются для создания читаемых и оптимизированных для SEO URL:

Строка слагов обычно содержит только символы a-z, 0-9 и - и поэтому может быть написана без URL-escaping (подумайте "foo% 20bar").

Я ищу функцию слагаемого Perl, которая, если любая допустимая строка Unicode вернет представление слага (a-z, 0-9 и -).

Супер тривиальная функция слагов будет выглядеть примерно так:

$input = lc($input),
$input =~ s/[^a-z0-9-]//g;

Однако эта реализация не будет обрабатывать интернационализацию и акценты (я хочу, чтобы ë стал e).Одним из способов обойти это было бы перечисление всех особых случаев, но это было бы не очень элегантно.Я ищу что-то более продуманное и общее.

Мой вопрос:

  • Какой самый общий / практичный способ генерировать слагов типа Django / Rails вPerl? Это , как я решил ту же проблему в Java.

Ответы [ 5 ]

12 голосов
/ 24 октября 2010

Фильтр slugify , используемый в настоящее время в Django, переводит (примерно) следующий код Perl:

use Unicode::Normalize;

sub slugify($) {
    my ($input) = @_;

    $input = NFKD($input);         # Normalize (decompose) the Unicode string
    $input =~ tr/\000-\177//cd;    # Strip non-ASCII characters (>127)
    $input =~ s/[^\w\s-]//g;       # Remove all characters that are not word characters (includes _), spaces, or hyphens
    $input =~ s/^\s+|\s+$//g;      # Trim whitespace from both ends
    $input = lc($input);
    $input =~ s/[-\s]+/-/g;        # Replace all occurrences of spaces and hyphens with a single hyphen

    return $input;
}

Поскольку вы также хотите поменять символы с акцентом на символы без акцента, лучше всего сделать ставку на unidecode (определено в Text::Unidecode) перед удалением символов не-ASCII (, как указано по файлону ).

В этом случае функция может выглядеть следующим образом:

use Unicode::Normalize;
use Text::Unidecode;

sub slugify_unidecode($) {
    my ($input) = @_;

    $input = NFC($input);          # Normalize (recompose) the Unicode string
    $input = unidecode($input);    # Convert non-ASCII characters to closest equivalents
    $input =~ s/[^\w\s-]//g;       # Remove all characters that are not word characters (includes _), spaces, or hyphens
    $input =~ s/^\s+|\s+$//g;      # Trim whitespace from both ends
    $input = lc($input);
    $input =~ s/[-\s]+/-/g;        # Replace all occurrences of spaces and hyphens with a single hyphen

    return $input;
}

Первый работает хорошо для строк, которые в основном являются ASCII, но не дотягивают до тех пор, пока вся строка не состоит из символов ASCII, так как все они удаляются, оставляя вас с пустой строкой.

Пример вывода:

string        | slugify       | slugify_unidecode
-------------------------------------------------
hello world     hello world     hello world
北亰                            bei-jing
liberté         liberta         liberte

Обратите внимание на то, что implementation lu превращается в тупик с реализацией, вдохновленной Django. Обратите внимание также на разницу, которую делает нормализация NFC - liberté становится 'liberta' с NFKD после удаления второй части разложенного символа, но становится 'libert' после удаления вновь собранного 'é' с NFC.

3 голосов
/ 24 октября 2010

String::Dirify используется для создания слагов в программном обеспечении блогов Movable Type / Melody.

3 голосов
/ 24 октября 2010

Вы ищете что-то вроде Текст :: Unidecode ?

1 голос
/ 24 октября 2010

Добавление Text :: Unaccent в начало цепочки выглядит так, как будто оно будет делать то, что вы хотите.

0 голосов
/ 14 июля 2015

Наиболее подходящим решением является использование Text :: Slugify , которое делает то, что вам нужно.Это тривиальный объем кода, который прекрасно предоставляет вам функцию slugify.

Он опирается на Text :: Unaccent :: PurePerl для удаления акцентов с символов.

...