用于生成 slug 的 Java 代码/库(用于漂亮的 URL)

Posted

技术标签:

【中文标题】用于生成 slug 的 Java 代码/库(用于漂亮的 URL)【英文标题】:Java code/library for generating slugs (for use in pretty URLs) 【发布时间】:2010-12-12 01:08:12 【问题描述】:

Rails 和 Django 等 Web 框架内置了对“slugs”的支持,这些“slugs”用于生成可读且对 SEO 友好的 URL:

Slugs in Rails Slugs in Django

一个 slug 字符串通常只包含字符 a-z0-9-,因此可以在没有 URL 转义的情况下编写(想想“foo%20bar”)。

我正在寻找一个 Java slug 函数,它给定任何有效的 Unicode 字符串都会返回一个 slug 表示(a-z0-9-)。

一个微不足道的 slug 函数应该是这样的:

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

但是,此实现不会处理国际化和重音符号 (ë > e)。解决这个问题的一种方法是枚举所有特殊情况,但这不是很优雅。我正在寻找更深思熟虑和更通用的东西。

我的问题:

在 Java 中生成 Django/Rails 类型 slug 最通用/实用的方法是什么?

【问题讨论】:

【参考方案1】:

Normalize您的字符串使用规范分解:

  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),所以你如果您在土耳其语言环境下使用 String.toLowerCase(),则可能会在字符串中引入非 latin1 字符。

【讨论】:

看起来很有希望,但规范化似乎不起作用:“fóòbâr”被翻译成“fbr”而不是预期的“foobar”。你知道为什么吗? 奇怪 - 当我通过方法输入字符串"f\u00F3\u00F2b\u00e2r" 时,我得到"foobar"。您可能在源文件或数据文件中出现编码错误;见illegalargumentexception.blogspot.com/2009/05/… McDowell:你说的完全正确——这是一个编码错误。感谢您的出色回答!【参考方案2】:

http://search.maven.org/#search|ga|1|slugify

这里是 GitHub 存储库,可以查看代码及其用法:

https://github.com/slugify/slugify

【讨论】:

迄今为止最好的可扩展解决方案。【参考方案3】:

我已经扩展了@McDowell 的答案,包括将标点符号转义为连字符并删除重复和前导/尾随连字符。

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

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

【讨论】:

【参考方案4】:

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

【讨论】:

以上是关于用于生成 slug 的 Java 代码/库(用于漂亮的 URL)的主要内容,如果未能解决你的问题,请参考以下文章

django 1.9 slug 字段不适用于外语

用于字符序列生成器的 Java 库

Slug 字段不适用于 django 中的孟加拉语。如何在孟加拉语中使用蛞蝓

如何检测用于创建 slug 的输入语言,如果不是英语,那么 slug 输入使用 javascript 保持为空

用于自定义帖子类型的 Wordpress 多个 slug

用于创建图形的 Java 库 [关闭]