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()
под турецкой локалью.
А вот репозиторий GitHub, чтобы взглянуть на код и его использование:
Предложение 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