Java-код / ​​библиотека для генерации слагов (для использования в красивых URL)

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

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

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

Тривиальная функция слагов будет чем-то вроде:

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

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

Мой вопрос:

  • Каков наиболее общий / практичный способ создания слагов типа Django/Rails в Java?

5 ответов

Решение

Нормализуйте свою строку, используя каноническое разложение:

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

Это все еще довольно наивный процесс. Он не собирается ничего делать для s-sharp (ß - используется на немецком языке) или любого нелатинского алфавита (греческий, кириллица, CJK и т. Д.).

Будьте осторожны при изменении регистра строки. Прописные и строчные буквы зависят от алфавита. В турецком языке заглавные буквы U + 0069 (i) - U + 0130 (İ), а не U + 0049 (I), поэтому вы рискуете ввести нелатинский символ 1 обратно в строку, если вы используете String.toLowerCase() под турецкой локалью.

http://search.maven.org/

А вот репозиторий GitHub, чтобы взглянуть на код и его использование:

http://github.com/slugify/slugify

Предложение McDowel почти работает, но в подобных случаях Hello World !! это возвращается hello-world-- (Обратите внимание -- в конце строки) вместо hello-world,

Фиксированная версия может быть:

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

Я расширил ответ @McDowell, включив в него дефисы в качестве дефисов и удалив дубликаты и начальные / конечные дефисы.

  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("^-|-$","");
  }

Справочная библиотека для других языков: http://www.codecodex.com/wiki/Generate_a_url_slug

Другие вопросы по тегам