2010-10-24 21 views
5

quadri Web come Rails e Django è dotato di supporto per "lumache" che vengono utilizzati per generare URL leggibili e SEO-friendly:Come posso generare slug URL in Perl?

Una stringa lumaca in genere contiene solo i caratteri a-z, 0-9 e - e può quindi essere scritto senza escape dell'URL (si pensi "pippo% 20bar").

Sto cercando una funzione Slug Perl che, dato qualsiasi stringa Unicode valido restituirà una rappresentazione lumaca (a-z, 0-9 e -).

Una funzione eccellente banale lumaca sarebbe qualcosa sulla falsariga di:

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

Tuttavia, questa implementazione non sarebbe gestire l'internazionalizzazione e gli accenti (voglio ë diventare e). Un modo per aggirare questo sarebbe enumerare tutti i casi speciali, ma non sarebbe molto elegante. Sto cercando qualcosa di più ben pensato e generale.

La mia domanda:

  • Qual è il/modo pratico più generale per generare Django/Rails tipo lumache in Perl?This è come ho risolto lo stesso problema in Java.
+0

Fai come hai fatto in Java. C'è una particolare operazione che non sai come tradurre? –

+0

brian: Sì, l'operazione che non sapevo come tradurre era "String normalized = Normalizer.normalize (nowhitespace, Form.NFD);". Unicode :: Normalize risolto. Guarda la risposta di Cameron. – knorv

risposta

11

Il slugify filter attualmente utilizzato in Django traduce (approssimativamente) al seguente codice 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; 
} 

Dal momento che si vuole anche cambiare i caratteri accentati a quelle non accentate, gettando in una chiamata a unidecode (definito in Text::Unidecode) prima di rimuovere i caratteri non ASCII sembra essere la soluzione migliore (as pointed out by phaylon).

In questo caso, la funzione potrebbe essere simile:

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; 
} 

Il primo funziona bene per le stringhe che sono principalmente ASCII, ma è inferiore quando l'intera stringa è formato da caratteri non ASCII, dal momento che tutti spogliati, lasciandoti con una corda vuota.

Esempio di output:

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

Si noti come 北 亰 ottiene slugifies per nulla con l'attuazione Django di ispirazione. Notare anche la differenza con la normalizzazione NFC: liberté diventa "liberta" con NFKD dopo aver rimosso la seconda parte del carattere scomposto, ma diventa "libert" dopo aver rimosso il riassemblato "é" con NFC.

3

String::Dirify viene utilizzato per la creazione di lumache nel software di blogging Movable Type/Melody.

+0

Fa unicode o solo ISO-8859? – MkV

+0

Codepoints oltre il 255 non sono toccati. – daxim

+0

Testato con alcuni cinesi, sembra quello di cui ho bisogno. – Weiyan

0

La soluzione più chiavi in ​​mano è l'utilizzo di Text::Slugify che fa ciò che ti serve. È una quantità insignificante di codice che fornisce in modo semplice una funzione slugify per te.

Si basa su Text::Unaccent::PurePerl per rimuovere gli accenti dai caratteri.

Problemi correlati