2009-11-01 5 views
31

Webフレームワーク:Javaのナメクジを生成するためのコード/ライブラリ(プリティURLで使用するため)

スラグ文字列は通常、文字だけa-z0-9-、したがってずに書き込むことができるの含まURLエスケープ(だと思う「のfoo%の20BA r ")。

有効なUnicode文字列がスラッグ表現(a-z,0-9および-)を返すJavaスラッグ関数を探しています。しかし、この実装は国際化とアクセント(>eë)を処理しません

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

些細なスラグ機能は、の線に沿って何かだろう。これを回避する方法の1つは、すべての特別なケースを列挙することですが、それほどエレガントではありません。私はもっ​​とよく考えられたものを探しています。

私の質問:

  • Javaでジャンゴ/ Railsのタイプスラグを生成するための最も一般的/実用的な方法は何ですか?標準的な分解を使用して

答えて

34

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シャープ(ドイツ語で使用されるß)やラテン文字以外のアルファベット(ギリシャ語、キリル文字、CJKなど)は何もしません。

文字列の大文字と小文字を変更するときは注意してください。大文字と小文字はアルファベットに依存します。トルコでは、U + 0069(I)の総額はU + 0130(İ)ではなく、U + 0049(I)であるので、あなたはString.toLowerCase()を使用する場合は、戻ってあなたの文字列にlatin1以外の文字を導入する危険性トルコのロケールの下で。他の言語のための

+1

有望に見えるが、正規化は、動作するように表示されません:「foobarには」代わりに期待「foobarに」の「FBR」に変換されます。なぜなのかご存知ですか? – knorv

+1

奇妙な - 私は、文字列 '' f \ u00F3 \ u00F2b \ u00e2r ''をメソッドを通して渡すと '' foobar "'を得る。ソースファイルやデータファイルにエンコードエラーが発生している可能性があります。 http://illegalargumentexception.blogspot.com/2009/05/java-rough-guide-to-character-encoding.html – McDowell

+0

を参照してください。McDowell:あなたは間違いなく、エンコードエラーです。優れた答えをありがとう! – knorv

1

私はしました@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("^-|-$",""); 
    } 
1

McDowelの命題はほとんど動作しますが、このHello World !!ような場合には(文字列の最後に--に注意してください)の代わりに、hello-worldhello-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(text).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); 
} 
関連する問題