Código/biblioteca Java para generar slugs (para usar en URLs bonitas)


Los marcos web como Rails y Django tienen soporte incorporado para "slugs" que se utilizan para generar URL legibles y amigables con el SEO:

Una cadena de slug normalmente contiene solo los caracteres a-z, 0-9 y - y por lo tanto se puede escribir sin escape de URL (piense en "foo%20bar").

Estoy buscando una función slug Java que, dada cualquier cadena Unicode válida, devolverá un slug representación (a-z, 0-9 y -).

Una función de slug trivial sería algo así como:

return input.toLowerCase().replaceAll("[^a-z0-9-]", "");

Sin embargo, esta implementación no manejaría la internacionalización y los acentos (ë > e). Una forma de evitar esto sería enumerar todos los casos especiales, pero eso no sería muy elegante. Estoy buscando algo más bien pensado y general.

Mi pregunta:

  • Cuál es la forma más general/práctica de generar ¿Django / Rails escribe slugs en Java?
Author: Community, 2009-11-01

5 answers

Normaliza tu cadena usando descomposición canónica:

  private static final Pattern NONLATIN = Pattern.compile("[^\\w-]");
  private static final Pattern WHITESPACE = Pattern.compile("[\\s]");

  public static String toSlug(String input) {
    String nowhitespace = WHITESPACE.matcher(input).replaceAll("-");
    String normalized = Normalizer.normalize(nowhitespace, Form.NFD);
    String slug = NONLATIN.matcher(normalized).replaceAll("");
    return slug.toLowerCase(Locale.ENGLISH);
  }

Este es todavía un proceso bastante ingenuo, sin embargo. No va a hacer nada para s-sharp (ß - utilizado en alemán), o cualquier alfabeto no basado en latín (griego, Cirílico, CJK, etc.).

tenga cuidado al cambiar el caso de una cadena. Las formas mayúsculas y minúsculas dependen de alfabetos. En turco, la capitalización de U+0069 (i) es U+0130 (I), no U+0049 (I), por lo que corra el riesgo de introducir un carácter no latin1 de nuevo en su cadena si utiliza String.toLowerCase() bajo una configuración regional turca.

 35
Author: McDowell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-01 14:38:07

Http://search.maven.org/#search/ga/1/slugify

Y aquí está el repositorio GitHub para echar un vistazo al código y su uso:

Https://github.com/slugify/slugify

 10
Author: dtrunk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-17 17:42:32

Biblioteca de referencia, para otros idiomas: http://www.codecodex.com/wiki/Generate_a_url_slug

 1
Author: Rafael Sanches,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-02 00:08:46

He ampliado la respuesta de @McDowell para incluir la puntuación de escape como guiones y para eliminar guiones duplicados e iniciales/finales.

  private static final Pattern NONLATIN = Pattern.compile("[^\\w_-]");  
  private static final Pattern SEPARATORS = Pattern.compile("[\\s\\p{Punct}&&[^-]]");  

  public static String makeSlug(String input) {  
    String noseparators = SEPARATORS.matcher(input).replaceAll("-");
    String normalized = Normalizer.normalize(noseparators, Form.NFD);
    String slug = NONLATIN.matcher(normalized).replaceAll("");
    return slug.toLowerCase(Locale.ENGLISH).replaceAll("-{2,}","-").replaceAll("^-|-$","");
  }
 1
Author: Mike Godin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-20 16:21:11

La proposición de McDowel casi funciona, pero en casos como este Hello World !! devuelve hello-world-- (note el -- al final de la cadena) en lugar de hello-world.

Una versión fija podría ser:

private static final Pattern NONLATIN = Pattern.compile("[^\\w-]");
private static final Pattern WHITESPACE = Pattern.compile("[\\s]");
private static final Pattern EDGESDHASHES = Pattern.compile("(^-|-$)");

public static String toSlug(String input) {
    String nowhitespace = WHITESPACE.matcher(input).replaceAll("-");
    String normalized = Normalizer.normalize(nowhitespace, Normalizer.Form.NFD);
    String slug = NONLATIN.matcher(normalized).replaceAll("");
    slug = EDGESDHASHES.matcher(slug).replaceAll("");
    return slug.toLowerCase(Locale.ENGLISH);
}
 1
Author: Mariano Ruiz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-25 13:42:49