2009-11-01 18 views
31

Web çerçeveler yerleşik destek okunabilir ve SEO dostu URL'ler oluşturmak için kullanılan "salyangozlar" için (güzel URL'lerin kullanılmak üzere) sümüklü böcek üretmek için kütüphane:Java kodu/böyle Raylar ve Django olarak

bir sümüklü böcek dize genellikle yalnızca karakterlerin a-z, 0-9 ve - ve dolayısıyla olmadan yazılabilir ait içeren URL kaçan (düşünmek "foo% 20ba r ").

Bir sümüklü böcek temsilini (a-z, 0-9 ve -) dönecektir herhangi geçerli Unicode dizesi verilen bir Java sülük fonksiyonu arıyorum.

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

Ancak bu uygulama işlemek olmaz uluslararası ve aksan (>eë):

Önemsiz bir sülük fonksiyonu çizgisinde bir şey olurdu. Bunun bir yolu tüm özel durumları sıralamak olurdu, ama bu çok zarif olmazdı. Daha iyi düşünülmüş ve genel bir şey arıyorum.

Sorum:

  • Java Django/Raylar tipi salyangozlar üretmek için en genel/pratik yolu nedir? Kurallı bir oluşuma kullanarak

cevap

34

Normalize dize:

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

Bu da, hala oldukça naif bir süreçtir. S-keskin (Almanca dilinde kullanılan ß) veya Latin kökenli olmayan herhangi bir alfabe (Yunanca, Kiril, CJK, vb.) Için hiçbir şey yapmayacaktır.

Dizenin durumunu değiştirirken dikkatli olun. Üst ve alt durum formları alfabe bağımlıdır. Türk olarak, + 0069 U harf (i) 'dir U + 0130 (İ) değil, U + 0049 (ı) bu yüzden size String.toLowerCase() kullanırsanız, dize geri olmayan bir latin1 karakter tanıtan riske bir Türk yöresinde. Diğer diller için

+1

umut verici görünüyor, ama normalleşme çalışmak görünmüyor: "filanca" "yüzenler" yerine beklenen "filanca" tercüme alır. Neden biliyor musun? – knorv

+1

Garip - "f \ u00F3 \ u00F2b \ u00e2r" dizesini yöntemle koyduğumda, "foobar" sözcüğünü alıyorum. Kaynak veya veri dosyanızda bir kodlama hatası oluşturuyor olabilirsiniz; bkz http://illegalargumentexception.blogspot.com/2009/05/java-rough-guide-to-character-encoding.html – McDowell

+0

McDowell: Kesinlikle haklısınız - bir kodlama hatasıydı. Mükemmel bir cevap için teşekkürler! – knorv

8

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

Ve bir kodun bakmak ve kullanımını almaya GitHub depo bulunuyor Yanıtla, noktalama işaretlemelerini tire olarak eklemek ve yinelenen ve öndeki/sondaki tire işaretlerini kaldırmak için @McDowell tarafından verilen yanıtı genişletti.

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

Şimdiye kadar en iyi ve genişletilebilir çözüm. – Ankur

1

McDowel önermesi neredeyse çalışır, ancak bu Hello World !! gibi durumlarda (dizesinin sonunda -- unutmayın) yerine hello-worldhello-world-- döndürür.

bir sabit versiyonu olabilir:

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