स्टैक ओवरफ्लो अपने एसईओ के अनुकूल URL कैसे उत्पन्न करता है?


253

एक पूर्ण पूर्ण नियमित अभिव्यक्ति या कोई अन्य प्रक्रिया जो शीर्षक लेती है:

Stack Overflow जैसे URL का हिस्सा बनने के लिए आप शीर्षक कैसे बदलते हैं?

और इसे चालू करें

how-do-you-change-a-title-to-be-part-of-the-url-like-stack-overflow

स्टैक ओवरफ्लो पर एसईओ के अनुकूल URL में इसका उपयोग किया जाता है?

मैं जिस विकास के माहौल का उपयोग कर रहा हूं, वह रूबी ऑन रेल्स है , लेकिन अगर कुछ अन्य प्लेटफ़ॉर्म-विशिष्ट समाधान (.NET, PHP, Django ) हैं, तो मैं उन्हें भी देखना पसंद करूंगा।

मुझे यकीन है कि मैं (या एक और पाठक) लाइन के नीचे एक अलग प्लेटफॉर्म पर एक ही समस्या से आऊंगा।

मैं कस्टम मार्गों का उपयोग कर रहा हूं, और मैं मुख्य रूप से जानना चाहता हूं कि स्ट्रिंग को सभी विशेष वर्णों में कैसे बदला जाए, यह सभी लोअरकेस है, और सभी व्हाट्सएप को बदल दिया गया है।


मजाकिया किरदारों का क्या? आप उन लोगों के बारे में क्या करने जा रहे हैं? उमलॉट? विराम चिह्न? इन पर विचार करने की आवश्यकता है। मूल रूप से, मैं एक श्वेत-सूची के दृष्टिकोण का उपयोग करूंगा, जैसा कि ऊपर-काली सूची के दृष्टिकोण के विपरीत है: वर्णन करें कि आप कौन से वर्णों की अनुमति देंगे, आप कौन से वर्णों को परिवर्तित करेंगे (किसको?) और फिर शेष को कुछ सार्थक ("") में बदल देंगे। । मुझे संदेह है कि आप इसे एक रेगेक्स में कर सकते हैं ... पात्रों के माध्यम से सिर्फ लूप क्यों नहीं?
डैरन थॉमस

1
मेटा में माइग्रेट किया जाना चाहिए ; सवाल और जवाब के रूप में दोनों विशेष रूप से SO कार्यान्वयन से निपटते हैं, और स्वीकृत उत्तर @JeffAtwood से है।
कैस्परऑन

19
@casperOne क्या आपको लगता है कि जेफ को कुछ गैर-मेटा प्रतिष्ठा की अनुमति नहीं है? सवाल यह है कि "कोई ऐसा कैसे कर सकता है", विशेष रूप से "यह यहाँ कैसे किया जाता है"।
पाओलो एबरमन

@ Pa @loEbermann: यह जेफ के बारे में कुछ गैर-मेटा प्रतिष्ठा प्राप्त करने के बारे में नहीं है (उसकी कितनी प्रतिष्ठा है यह वास्तव में मेरी चिंता नहीं है); प्रश्न निकाय ने विशेष रूप से StackOverflow के कार्यान्वयन को संदर्भित किया है, इसलिए इसके लिए तर्क मेटा पर है।
कैस्परऑन

जवाबों:


300

यहाँ हम इसे कैसे करते हैं। ध्यान दें कि पहली नज़र में आपको महसूस होने की तुलना में संभवतः अधिक किनारे की स्थिति है।

यह दूसरा संस्करण है, 5x अधिक प्रदर्शन के लिए अनियंत्रित (और हां, मैंने इसे बेंचमार्क किया)। मुझे लगा कि मैं इसे ऑप्टिमाइज़ करूंगा क्योंकि इस फ़ंक्शन को प्रति पृष्ठ सैकड़ों बार कहा जा सकता है।

/// <summary>
/// Produces optional, URL-friendly version of a title, "like-this-one". 
/// hand-tuned for speed, reflects performance refactoring contributed
/// by John Gietzen (user otac0n) 
/// </summary>
public static string URLFriendly(string title)
{
    if (title == null) return "";

    const int maxlen = 80;
    int len = title.Length;
    bool prevdash = false;
    var sb = new StringBuilder(len);
    char c;

    for (int i = 0; i < len; i++)
    {
        c = title[i];
        if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))
        {
            sb.Append(c);
            prevdash = false;
        }
        else if (c >= 'A' && c <= 'Z')
        {
            // tricky way to convert to lowercase
            sb.Append((char)(c | 32));
            prevdash = false;
        }
        else if (c == ' ' || c == ',' || c == '.' || c == '/' || 
            c == '\\' || c == '-' || c == '_' || c == '=')
        {
            if (!prevdash && sb.Length > 0)
            {
                sb.Append('-');
                prevdash = true;
            }
        }
        else if ((int)c >= 128)
        {
            int prevlen = sb.Length;
            sb.Append(RemapInternationalCharToAscii(c));
            if (prevlen != sb.Length) prevdash = false;
        }
        if (i == maxlen) break;
    }

    if (prevdash)
        return sb.ToString().Substring(0, sb.Length - 1);
    else
        return sb.ToString();
}

कोड के पिछले संस्करण को देखने के लिए इसे बदला गया (लेकिन कार्यात्मक रूप से और 5x तेज के बराबर), इस पोस्ट का संशोधन इतिहास (दिनांक लिंक पर क्लिक करें) देखें।

साथ ही, RemapInternationalCharToAsciiविधि स्रोत कोड यहां पाया जा सकता है


24
यह एक ऐसे संस्करण के साथ अच्छा होगा जो सिर्फ ääö जैसे उच्चारण वाले पात्रों को नहीं छोड़ता है, बल्कि उन्हें aao में बहक जाता है ... ^ ^
Oskar Duveborn

22
@oskar उस RemapInternationalCharToAscii()समारोह का ठप्पा है meta.stackexchange.com/questions/7435/…
Jeff Atwood

3
यह भी खूब रही। एकमात्र परिवर्तन जो मैंने अब तक किया है, वह है "अगर (i == अधिकतम) विराम को बदलना है;" "अगर (sb.Length == maxlen) विराम;" यदि मैं जिस तार से गुजर रहा हूं, उसमें बहुत सारे अमान्य चरित्र हैं।
टॉम चैंटलर

4
एक मामूली अनुकूलन: if (prevdash) sb.Length -= 1; return sb.ToString();अंतिम ifविवरण के बजाय ।
मार्क हर्ड

8
@ डूमर sb.Length == maxlen break;छोटी गाड़ी है अगर मैक्सलेन -1 पर साइन "it" है तो यह "ss" में परिवर्तित हो जाता है यह sb.Length == maxleneकभी भी सही नहीं होगा, इसके लिए परीक्षण करना बेहतर है (sb.Length > = maxlen)
हेनरिक स्टेनबक

32

यहाँ जेफ कोड का मेरा संस्करण है। मैंने निम्नलिखित परिवर्तन किए हैं:

  • हाइफ़न को इस तरह से जोड़ा गया था कि एक जोड़ा जा सके, और फिर इसे हटाने की आवश्यकता थी क्योंकि यह स्ट्रिंग में अंतिम चरित्र था। यही है, हम कभी नहीं चाहते हैं "मेरा-स्लग-"। इसका मतलब है कि इस किनारे के मामले को हटाने के लिए एक अतिरिक्त स्ट्रिंग आवंटन। मैंने देरी से-हाइफ़न करके इसके चारों ओर काम किया है। यदि आप मेरे कोड की तुलना जेफ़ से करते हैं तो इसके लिए तर्क का पालन करना आसान है।
  • उनका दृष्टिकोण विशुद्ध रूप से देखने पर आधारित है और स्टैक ओवरफ्लो पर शोध करते समय मैंने बहुत सारे पात्रों को याद किया। इसका मुकाबला करने के लिए, मैं पहली बार एक सामान्यीकरण पास को सुधारता हूं (मेटा स्टैक ओवरफ्लो प्रश्न में उल्लेखित AKA टकराव गैर यूएस- ASCII वर्ण पूर्ण (प्रोफ़ाइल) URL से हटा दिए गए हैं , और फिर स्वीकार्य श्रेणियों के बाहर किसी भी वर्ण को अनदेखा करते हैं। यह ज्यादातर समय काम करता है ...
  • ... जब यह नहीं होता है तो मुझे लुकअप टेबल भी जोड़ना पड़ता है। जैसा कि ऊपर उल्लेख किया गया है, कुछ वर्ण सामान्य होने पर कम ASCII मान पर मैप नहीं करते हैं। इन ड्रॉप के बजाय मुझे अपवादों की एक मैनुअल सूची मिली है जो कि संदेह से भरा है, लेकिन यह कुछ भी नहीं से बेहतर है। स्टैक ओवरफ्लो प्रश्न में जॉन हैना के महान पद से सामान्यीकरण कोड प्रेरित था मैं एक स्ट्रिंग पर लहजे को कैसे हटा सकता हूं?
  • केस रूपांतरण अब वैकल्पिक भी है।

    public static class Slug
    {
        public static string Create(bool toLower, params string[] values)
        {
            return Create(toLower, String.Join("-", values));
        }
    
        /// <summary>
        /// Creates a slug.
        /// References:
        /// http://www.unicode.org/reports/tr15/tr15-34.html
        /// /meta/7435/non-us-ascii-characters-dropped-from-full-profile-url/7696#7696
        /// /programming/25259/how-do-you-include-a-webpage-title-as-part-of-a-webpage-url/25486#25486
        /// /programming/3769457/how-can-i-remove-accents-on-a-string
        /// </summary>
        /// <param name="toLower"></param>
        /// <param name="normalised"></param>
        /// <returns></returns>
        public static string Create(bool toLower, string value)
        {
            if (value == null)
                return "";
    
            var normalised = value.Normalize(NormalizationForm.FormKD);
    
            const int maxlen = 80;
            int len = normalised.Length;
            bool prevDash = false;
            var sb = new StringBuilder(len);
            char c;
    
            for (int i = 0; i < len; i++)
            {
                c = normalised[i];
                if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))
                {
                    if (prevDash)
                    {
                        sb.Append('-');
                        prevDash = false;
                    }
                    sb.Append(c);
                }
                else if (c >= 'A' && c <= 'Z')
                {
                    if (prevDash)
                    {
                        sb.Append('-');
                        prevDash = false;
                    }
                    // Tricky way to convert to lowercase
                    if (toLower)
                        sb.Append((char)(c | 32));
                    else
                        sb.Append(c);
                }
                else if (c == ' ' || c == ',' || c == '.' || c == '/' || c == '\\' || c == '-' || c == '_' || c == '=')
                {
                    if (!prevDash && sb.Length > 0)
                    {
                        prevDash = true;
                    }
                }
                else
                {
                    string swap = ConvertEdgeCases(c, toLower);
    
                    if (swap != null)
                    {
                        if (prevDash)
                        {
                            sb.Append('-');
                            prevDash = false;
                        }
                        sb.Append(swap);
                    }
                }
    
                if (sb.Length == maxlen)
                    break;
            }
            return sb.ToString();
        }
    
        static string ConvertEdgeCases(char c, bool toLower)
        {
            string swap = null;
            switch (c)
            {
                case 'ı':
                    swap = "i";
                    break;
                case 'ł':
                    swap = "l";
                    break;
                case 'Ł':
                    swap = toLower ? "l" : "L";
                    break;
                case 'đ':
                    swap = "d";
                    break;
                case 'ß':
                    swap = "ss";
                    break;
                case 'ø':
                    swap = "o";
                    break;
                case 'Þ':
                    swap = "th";
                    break;
            }
            return swap;
        }
    }

अधिक विवरणों के लिए, यूनिट परीक्षण, और फेसबुक की URL योजना स्टैक ओवरफ्लो की तुलना में थोड़ी अधिक स्मार्ट क्यों है, इसका एक स्पष्टीकरण , मुझे अपने ब्लॉग पर इसका एक विस्तारित संस्करण मिला है ।


4
+1 यह महान दान है। मैंने आपके ब्लॉग पर संभवतः बदले if (i == maxlen) break;जाने के बारे में एक टिप्पणी भी जोड़ दी if (sb.Length == maxlen) break;ताकि यदि आप बहुत सारे व्हाट्सएप / अमान्य वर्णों के साथ स्ट्रिंग में पास हो जाते हैं, तो आप अभी भी वांछित लंबाई का एक स्लग प्राप्त कर सकते हैं, जबकि यह खड़ा होने वाला कोड समाप्त हो सकता है इसे बड़े पैमाने पर काट-छाँट (उदाहरण के लिए उस स्थिति पर विचार करें जहां आप 80 स्थानों से शुरू करते हैं ...)। और जेफ के कोड के खिलाफ 10,000,000 पुनरावृत्तियों के एक मोटे बेंचमार्क ने इसे लगभग उसी गति से दिखाया।
टॉम चैंटलर

1
धन्यवाद, मेरे ब्लॉग पर जवाब दिया और उसने वहां और ऊपर कोड निर्धारित किया। कोड बेंचमार्किंग के लिए भी धन्यवाद। रुचि रखने वालों के लिए यह जेफ के बराबर था।
दानह

2
ऐसा लगता है कि Slug.Create () के साथ कुछ समस्याएं हैं: ase के अपरकेस संस्करण को ठीक से परिवर्तित नहीं किया गया है converted को अनदेखा किया जाता है, जब। A में अनुवाद किया जाता है। आम तौर पर आप "å" को "आ", "ø" को "ओई" और "æ" को "एई" में बदल देंगे। दूसरा (sb.Length == maxlen) ब्रेक; बगिया है यदि मैक्सनल -1 पर चिन्ह "(" (sb.Length == maxlen) है तो यह कभी सही नहीं होगा बजाय इसके कि sb.Length> = maxlen के लिए परीक्षण करना बेहतर है। मैं दबा हुआ हूं कि आप किसी भी यादृच्छिक स्थिति में कटौती करते हैं और अंतिम पर नहीं काटते हैं - ", यह आपको अंत में एक वांछित शब्द के साथ समाप्त होने से बचाएगा: जैसे कि आपको अंतिम" के बाद "जोर लगाने के लिए" काटना था। "
हेनरिक स्टेनबाक

@DanH कोड का जावास्क्रिप्ट संस्करण होना बहुत अच्छा होगा।
फ्रेशब्लड

16

आप नियंत्रक को URL इंगित करने के लिए एक कस्टम मार्ग सेटअप करना चाहेंगे जो इसे संभाल लेगा। चूंकि आप रूबी ऑन रेल्स का उपयोग कर रहे हैं, यहाँ उनके रूटिंग इंजन का उपयोग करने में एक परिचय है।

रूबी में, आपको एक नियमित अभिव्यक्ति की आवश्यकता होगी, जैसा कि आप पहले से ही जानते हैं और यहां उपयोग करने के लिए नियमित अभिव्यक्ति है:

def permalink_for(str)
    str.gsub(/[^\w\/]|[!\(\)\.]+/, ' ').strip.downcase.gsub(/\ +/, '-')
end

11

आप इस जावास्क्रिप्ट फ़ंक्शन का उपयोग स्लग के इन-फॉर्म जनरेशन के लिए कर सकते हैं (यह एक Django से आधारित / कॉपी किया गया है ):

function makeSlug(urlString, filter) {
    // Changes, e.g., "Petty theft" to "petty_theft".
    // Remove all these words from the string before URLifying

    if(filter) {
        removelist = ["a", "an", "as", "at", "before", "but", "by", "for", "from",
        "is", "in", "into", "like", "of", "off", "on", "onto", "per",
        "since", "than", "the", "this", "that", "to", "up", "via", "het", "de", "een", "en",
        "with"];
    }
    else {
        removelist = [];
    }
    s = urlString;
    r = new RegExp('\\b(' + removelist.join('|') + ')\\b', 'gi');
    s = s.replace(r, '');
    s = s.replace(/[^-\w\s]/g, ''); // Remove unneeded characters
    s = s.replace(/^\s+|\s+$/g, ''); // Trim leading/trailing spaces
    s = s.replace(/[-\s]+/g, '-'); // Convert spaces to hyphens
    s = s.toLowerCase(); // Convert to lowercase
    return s; // Trim to first num_chars characters
}

कुछ लेट्स या कॉस्ट जोड़ना बहुत अच्छा होगा क्योंकि यह वैनिला JS नहीं है।
आदित्य आनंद

8

अच्छे उपाय के लिए, यहां वर्डप्रेस में PHP फ़ंक्शन है जो यह करता है ... मुझे लगता है कि वर्डप्रेस एक अधिक लोकप्रिय प्लेटफॉर्म है जो फैंसी लिंक का उपयोग करता है।

    समारोह sanitize_title_with_dashes ($ शीर्षक) {
            $ शीर्षक = पट्टी_टैग ($ शीर्षक);
            // संरक्षित बच गए ओकटेट्स।
            $ शीर्षक = preg_replace ('|% ([a-fA-F0-9] [a-fA-F0-9]) |', '--- $ 1 ---', $ शीर्षक;
            // ऐसे प्रतिशत संकेत निकालें जो एक ऑक्टेट का हिस्सा नहीं हैं।
            $ शीर्षक = str_replace ('%', '', $ शीर्षक);
            // ओक्टेट को पुनर्स्थापित करें।
            $ शीर्षक = preg_replace ('| --- ([a-fA-F0-9] [a-fA-F0-9]) --- |', '% $ 1', $ शीर्षक);
            $ शीर्षक = remove_accents ($ शीर्षक);
            अगर (लगता है_टर्फ 8 ($ शीर्षक)) {
                    अगर (function_exists ('mb_strtolower')) {
                            $ शीर्षक = mb_strtolower ($ शीर्षक, 'UTF-8');
                    }
                    $ शीर्षक = utf8_uri_encode ($ शीर्षक, 200);
            }
            $ शीर्षक = स्ट्रेटोलॉवर ($ शीर्षक);
            $ शीर्षक = preg_replace ('/ /&++///', '', $ शीर्षक); // संस्थाओं को मार डालो
            $ शीर्षक = preg_replace ('/ [^% a-z0-9 _-] /', '', $ शीर्षक);
            $ शीर्षक = preg_replace ('/ \ s + /', '-', $ शीर्षक);
            $ शीर्षक = preg_replace ('| - + |', '-', $ शीर्षक);
            $ शीर्षक = ट्रिम ($ शीर्षक, '-');
            $ शीर्षक लौटाएं;
    }

यह फ़ंक्शन और साथ ही कुछ सहायक कार्यों को wp- शामिल / formatting.php में पाया जा सकता है।


6
यह पूर्ण उत्तर नहीं है। आप जैसे कार्यों याद कर रहे हैं: remove_accents, seems_utf8...
निकोला लोंकर

पूरा @The कैसे-गीक के लिए आप अभी भी जवाब कर सकते हैं git clone git://core.git.wordpress.org/और पाते हैं wp-includes/formatting.phpमें फ़ाइल
mickro

5

यदि आप रेल के किनारे का उपयोग कर रहे हैं, तो आप Inflector.parametrize पर भरोसा कर सकते हैं - यहाँ प्रलेखन से उदाहरण दिया गया है:

  class Person
    def to_param
      "#{id}-#{name.parameterize}"
    end
  end

  @person = Person.find(1)
  # => #<Person id: 1, name: "Donald E. Knuth">

  <%= link_to(@person.name, person_path(@person)) %>
  # => <a href="https://stackoverflow.com/person/1-donald-e-knuth">Donald E. Knuth</a>

यदि आपको रेल के पिछले संस्करण में एक्सेंट (éphémère) जैसे अधिक विदेशी पात्रों को संभालने की आवश्यकता है, तो आप PermalinkFu और DiacriticsFu के मिश्रण का उपयोग कर सकते हैं :

DiacriticsFu::escape("éphémère")
=> "ephemere"

DiacriticsFu::escape("räksmörgås")
=> "raksmorgas"

5

मैं रूबी ऑन रेल्स से परिचित नहीं हूं, लेकिन निम्नलिखित (अप्रयुक्त) PHP कोड है। यदि आप इसे उपयोगी पाते हैं तो आप रूबी पर रूबी के लिए इसका बहुत जल्दी अनुवाद कर सकते हैं।

$sURL = "This is a title to convert to URL-format. It has 1 number in it!";
// To lower-case
$sURL = strtolower($sURL);

// Replace all non-word characters with spaces
$sURL = preg_replace("/\W+/", " ", $sURL);

// Remove trailing spaces (so we won't end with a separator)
$sURL = trim($sURL);

// Replace spaces with separators (hyphens)
$sURL = str_replace(" ", "-", $sURL);

echo $sURL;
// outputs: this-is-a-title-to-convert-to-url-format-it-has-1-number-in-it

आशा है कि ये आपकी मदद करेगा।


4

मैं रूबी या रेल के बारे में बहुत कुछ नहीं करता, लेकिन पर्ल में, मैं यही करूंगा:

my $title = "How do you change a title to be part of the url like Stackoverflow?";

my $url = lc $title;   # Change to lower case and copy to URL.
$url =~ s/^\s+//g;     # Remove leading spaces.
$url =~ s/\s+$//g;     # Remove trailing spaces.
$url =~ s/\s+/\-/g;    # Change one or more spaces to single hyphen.
$url =~ s/[^\w\-]//g;  # Remove any non-word characters.

print "$title\n$url\n";

मैंने बस एक त्वरित परीक्षण किया और यह काम करने लगता है। उम्मीद है कि रूबी के लिए अनुवाद करना अपेक्षाकृत आसान है।


4

T-SQL कार्यान्वयन, dbo.UrlEncode से अनुकूलित :

CREATE FUNCTION dbo.Slug(@string varchar(1024))
RETURNS varchar(3072)
AS
BEGIN
    DECLARE @count int, @c char(1), @i int, @slug varchar(3072)

    SET @string = replace(lower(ltrim(rtrim(@string))),' ','-')

    SET @count = Len(@string)
    SET @i = 1
    SET @slug = ''

    WHILE (@i <= @count)
    BEGIN
        SET @c = substring(@string, @i, 1)

        IF @c LIKE '[a-z0-9--]'
            SET @slug = @slug + @c

        SET @i = @i +1
    END

    RETURN @slug
END

4

मुझे पता है कि यह बहुत पुराना सवाल है, लेकिन चूंकि अधिकांश ब्राउज़र अब यूनिकोड यूआरएल का समर्थन करते हैं, मुझे एक्सजेक्स में एक शानदार समाधान मिला जो अक्षरों को छोड़कर (सभी भाषाओं में '-') में सब कुछ परिवर्तित करता है।

यह कई प्रोग्रामिंग भाषाओं में किया जा सकता है।

पैटर्न है \\p{^L}+और फिर आपको इसे सभी गैर अक्षरों को '-' में बदलने के लिए उपयोग करने की आवश्यकता है।

Xregex मॉड्यूल के साथ node.js में काम करने का उदाहरण ।

var text = 'This ! can @ have # several $ letters % from different languages such as עברית or Español';

var slugRegEx = XRegExp('((?!\\d)\\p{^L})+', 'g');

var slug = XRegExp.replace(text, slugRegEx, '-').toLowerCase();

console.log(slug) ==> "this-can-have-several-letters-from-different-languages-such-as-עברית-or-español"

3

यह मानते हुए कि आपके मॉडल वर्ग में एक शीर्षक विशेषता है, आप इस तरह से मॉडल के भीतर_परम पद्धति को ओवरराइड कर सकते हैं, जैसे:

def to_param
  title.downcase.gsub(/ /, '-')
end

इस Railscast प्रकरण में सभी विवरण हैं। आप यह भी सुनिश्चित कर सकते हैं कि शीर्षक में केवल इसका उपयोग करने वाले मान्य वर्ण हैं:

validates_format_of :title, :with => /^[a-z0-9-]+$/,
                    :message => 'can only contain letters, numbers and hyphens'

2

रूबी में ब्रायन का कोड:

title.downcase.strip.gsub(/\ /, '-').gsub(/[^\w\-]/, '')

downcaseस्ट्रिंग को कम करने के लिए बदल जाता है, stripप्रमुख और अनुगामी व्हाट्सएप को हटाता है, पहला gsubकॉल जी लॉबली उप मंचित स्थान को डैश के साथ, और दूसरा सब कुछ हटा देता है जो एक पत्र या डैश नहीं है।


2

PermalinkFu नामक रेल्स प्लगइन पर एक छोटी सी रूबी है , जो ऐसा करती है। भागने विधि एक स्ट्रिंग एक के लिए उपयुक्त है कि में परिवर्तन करता है यूआरएल । कोड पर एक नज़र है; यह विधि काफी सरल है।

गैर- ASCII वर्णों को हटाने के लिए यह 'utf-8' से 'ascii // अनदेखा // ट्रांसलिट' में अनुवाद करने के लिए iconv लिब का उपयोग करता है। रिक्त स्थान फिर डैश में बदल जाते हैं, सब कुछ नीचे गिर जाता है, आदि।


हालांकि यह पूरी तरह से काम करता है, मुझे लगता है कि यह बहुत ही कुशल है।
WhyNotHugo

2

आप निम्न सहायक विधि का उपयोग कर सकते हैं। यह यूनिकोड वर्णों को परिवर्तित कर सकता है।

public static string ConvertTextToSlug(string s)
{
    StringBuilder sb = new StringBuilder();

    bool wasHyphen = true;

    foreach (char c in s)
    {
        if (char.IsLetterOrDigit(c))
        {
            sb.Append(char.ToLower(c));
            wasHyphen = false;
        }
        else
            if (char.IsWhiteSpace(c) && !wasHyphen)
            {
                sb.Append('-');
                wasHyphen = true;
            }
    }

    // Avoid trailing hyphens
    if (wasHyphen && sb.Length > 0)
        sb.Length--;

    return sb.ToString().Replace("--","-");
}

2

यहाँ है मेरे (धीमी, लेकिन लिखने के लिए मजेदार) जेफ कोड का संस्करण:

public static string URLFriendly(string title)
{
    char? prevRead = null,
        prevWritten = null;

    var seq = 
        from c in title
        let norm = RemapInternationalCharToAscii(char.ToLowerInvariant(c).ToString())[0]
        let keep = char.IsLetterOrDigit(norm)
        where prevRead.HasValue || keep
        let replaced = keep ? norm
            :  prevWritten != '-' ? '-'
            :  (char?)null
        where replaced != null
        let s = replaced + (prevRead == null ? ""
            : norm == '#' && "cf".Contains(prevRead.Value) ? "sharp"
            : norm == '+' ? "plus"
            : "")
        let _ = prevRead = norm
        from written in s
        let __ = prevWritten = written
        select written;

    const int maxlen = 80;  
    return string.Concat(seq.Take(maxlen)).TrimEnd('-');
}

public static string RemapInternationalCharToAscii(string text)
{
    var seq = text.Normalize(NormalizationForm.FormD)
        .Where(c => CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark);

    return string.Concat(seq).Normalize(NormalizationForm.FormC);
}

मेरा परीक्षण स्ट्रिंग:

" I love C#, F#, C++, and... Crème brûlée!!! They see me codin'... they hatin'... tryin' to catch me codin' dirty... "


2

Stackoverflow समाधान महान है, लेकिन आधुनिक ब्राउज़र (आईई को छोड़कर, हमेशा की तरह) अब अच्छी तरह से UTF8 एन्कोडिंग संभाल:

यहां छवि विवरण दर्ज करें

इसलिए मैंने प्रस्तावित समाधान को अपग्रेड किया:

public static string ToFriendlyUrl(string title, bool useUTF8Encoding = false)
{
    ...

        else if (c >= 128)
        {
            int prevlen = sb.Length;
            if (useUTF8Encoding )
            {
                sb.Append(HttpUtility.UrlEncode(c.ToString(CultureInfo.InvariantCulture),Encoding.UTF8));
            }
            else
            {
                sb.Append(RemapInternationalCharToAscii(c));
            }
    ...
}

Pastebin पर पूर्ण कोड

संपादित करें: यहांRemapInternationalCharToAscii विधि के लिए कोड है (यह पास्टबिन में गायब है)।


विकिपीडिया के अनुसार , मोज़िला 1.4, नेटस्केप 7.1, ओपेरा 7.11 आईडीएनए का समर्थन करने वाले पहले अनुप्रयोगों में से थे। आईडीएन समर्थन प्रदान करने के लिए इंटरनेट एक्सप्लोरर 6 के लिए एक ब्राउज़र प्लगइन उपलब्ध है। इंटरनेट एक्सप्लोरर 7.0 और विंडोज विस्टा के यूआरएल एपीआई आईडीएन के लिए मूल समर्थन प्रदान करते हैं। UTF-8 वर्णों को हटाने जैसी ध्वनियाँ समय की बर्बादी हैं। लंबे समय तक जीवित रहें UTF-8 !!!
मुहम्मद रेहान सईद

1

मुझे नियमित अभिव्यक्ति का उपयोग किए बिना यह तरीका पसंद आया , इसलिए मैंने इसे PHP में पोर्ट किया। मैंने is_betweenपात्रों को जांचने के लिए एक फ़ंक्शन जोड़ा :

function is_between($val, $min, $max)
{
    $val = (int) $val; $min = (int) $min; $max = (int) $max;

    return ($val >= $min && $val <= $max);
}

function international_char_to_ascii($char)
{
    if (mb_strpos('àåáâäãåa', $char) !== false)
    {
        return 'a';
    }

    if (mb_strpos('èéêëe', $char) !== false)
    {
        return 'e';
    }

    if (mb_strpos('ìíîïi', $char) !== false)
    {
        return 'i';
    }

    if (mb_strpos('òóôõö', $char) !== false)
    {
        return 'o';
    }

    if (mb_strpos('ùúûüuu', $char) !== false)
    {
        return 'u';
    }

    if (mb_strpos('çccc', $char) !== false)
    {
        return 'c';
    }

    if (mb_strpos('zzž', $char) !== false)
    {
        return 'z';
    }

    if (mb_strpos('ssšs', $char) !== false)
    {
        return 's';
    }

    if (mb_strpos('ñn', $char) !== false)
    {
        return 'n';
    }

    if (mb_strpos('ýÿ', $char) !== false)
    {
        return 'y';
    }

    if (mb_strpos('gg', $char) !== false)
    {
        return 'g';
    }

    if (mb_strpos('r', $char) !== false)
    {
        return 'r';
    }

    if (mb_strpos('l', $char) !== false)
    {
        return 'l';
    }

    if (mb_strpos('d', $char) !== false)
    {
        return 'd';
    }

    if (mb_strpos('ß', $char) !== false)
    {
        return 'ss';
    }

    if (mb_strpos('Þ', $char) !== false)
    {
        return 'th';
    }

    if (mb_strpos('h', $char) !== false)
    {
        return 'h';
    }

    if (mb_strpos('j', $char) !== false)
    {
        return 'j';
    }
    return '';
}

function url_friendly_title($url_title)
{
    if (empty($url_title))
    {
        return '';
    }

    $url_title = mb_strtolower($url_title);

    $url_title_max_length   = 80;
    $url_title_length       = mb_strlen($url_title);
    $url_title_friendly     = '';
    $url_title_dash_added   = false;
    $url_title_char = '';

    for ($i = 0; $i < $url_title_length; $i++)
    {
        $url_title_char     = mb_substr($url_title, $i, 1);

        if (strlen($url_title_char) == 2)
        {
            $url_title_ascii    = ord($url_title_char[0]) * 256 + ord($url_title_char[1]) . "\r\n";
        }
        else
        {
            $url_title_ascii    = ord($url_title_char);
        }

        if (is_between($url_title_ascii, 97, 122) || is_between($url_title_ascii, 48, 57))
        {
            $url_title_friendly .= $url_title_char;

            $url_title_dash_added = false;
        }
        elseif(is_between($url_title_ascii, 65, 90))
        {
            $url_title_friendly .= chr(($url_title_ascii | 32));

            $url_title_dash_added = false;
        }
        elseif($url_title_ascii == 32 || $url_title_ascii == 44 || $url_title_ascii == 46 || $url_title_ascii == 47 || $url_title_ascii == 92 || $url_title_ascii == 45 || $url_title_ascii == 47 || $url_title_ascii == 95 || $url_title_ascii == 61)
        {
            if (!$url_title_dash_added && mb_strlen($url_title_friendly) > 0)
            {
                $url_title_friendly .= chr(45);

                $url_title_dash_added = true;
            }
        }
        else if ($url_title_ascii >= 128)
        {
            $url_title_previous_length = mb_strlen($url_title_friendly);

            $url_title_friendly .= international_char_to_ascii($url_title_char);

            if ($url_title_previous_length != mb_strlen($url_title_friendly))
            {
                $url_title_dash_added = false;
            }
        }

        if ($i == $url_title_max_length)
        {
            break;
        }
    }

    if ($url_title_dash_added)
    {
        return mb_substr($url_title_friendly, 0, -1);
    }
    else
    {
        return $url_title_friendly;
    }
}

1

अब सभी ब्राउज़र अच्छी तरह से utf8 एन्कोडिंग को संभालते हैं, इसलिए आप WebUtility.UrlEncode मेथड का उपयोग कर सकते हैं , जैसे कि HttpUtility.UrlEncode @giamin द्वारा उपयोग किया जाता है, लेकिन यह एक वेब एप्लिकेशन के बाहर काम करता है।


1

मैंने टाइपस्क्रिप्ट के लिए कोड को पोर्ट किया। इसे आसानी से जावास्क्रिप्ट के लिए अनुकूलित किया जा सकता है।

मैं प्रोटोटाइप में एक .containsविधि जोड़ रहा हूं String, यदि आप नवीनतम ब्राउज़रों या ES6 को लक्षित कर रहे हैं तो आप .includesइसके बजाय उपयोग कर सकते हैं ।

if (!String.prototype.contains) {
    String.prototype.contains = function (check) {
        return this.indexOf(check, 0) !== -1;
    };
}

declare interface String {
    contains(check: string): boolean;
}

export function MakeUrlFriendly(title: string) {
            if (title == null || title == '')
                return '';

            const maxlen = 80;
            let len = title.length;
            let prevdash = false;
            let result = '';
            let c: string;
            let cc: number;
            let remapInternationalCharToAscii = function (c: string) {
                let s = c.toLowerCase();
                if ("àåáâäãåą".contains(s)) {
                    return "a";
                }
                else if ("èéêëę".contains(s)) {
                    return "e";
                }
                else if ("ìíîïı".contains(s)) {
                    return "i";
                }
                else if ("òóôõöøőð".contains(s)) {
                    return "o";
                }
                else if ("ùúûüŭů".contains(s)) {
                    return "u";
                }
                else if ("çćčĉ".contains(s)) {
                    return "c";
                }
                else if ("żźž".contains(s)) {
                    return "z";
                }
                else if ("śşšŝ".contains(s)) {
                    return "s";
                }
                else if ("ñń".contains(s)) {
                    return "n";
                }
                else if ("ýÿ".contains(s)) {
                    return "y";
                }
                else if ("ğĝ".contains(s)) {
                    return "g";
                }
                else if (c == 'ř') {
                    return "r";
                }
                else if (c == 'ł') {
                    return "l";
                }
                else if (c == 'đ') {
                    return "d";
                }
                else if (c == 'ß') {
                    return "ss";
                }
                else if (c == 'Þ') {
                    return "th";
                }
                else if (c == 'ĥ') {
                    return "h";
                }
                else if (c == 'ĵ') {
                    return "j";
                }
                else {
                    return "";
                }
            };

            for (let i = 0; i < len; i++) {
                c = title[i];
                cc = c.charCodeAt(0);

                if ((cc >= 97 /* a */ && cc <= 122 /* z */) || (cc >= 48 /* 0 */ && cc <= 57 /* 9 */)) {
                    result += c;
                    prevdash = false;
                }
                else if ((cc >= 65 && cc <= 90 /* A - Z */)) {
                    result += c.toLowerCase();
                    prevdash = false;
                }
                else if (c == ' ' || c == ',' || c == '.' || c == '/' || c == '\\' || c == '-' || c == '_' || c == '=') {
                    if (!prevdash && result.length > 0) {
                        result += '-';
                        prevdash = true;
                    }
                }
                else if (cc >= 128) {
                    let prevlen = result.length;
                    result += remapInternationalCharToAscii(c);
                    if (prevlen != result.length) prevdash = false;
                }
                if (i == maxlen) break;
            }

            if (prevdash)
                return result.substring(0, result.length - 1);
            else
                return result;
        }

0

नहीं नहीं नहीं। तुम सब बहुत गलत हो। डायक्टिरिक्स-फू सामान को छोड़कर, आप वहां पहुंच रहे हैं, लेकिन एशियाई पात्रों के बारे में क्या है (अपने nihonjin brethren पर विचार नहीं करने के लिए रूबी डेवलपर्स पर शर्म की बात है )।

फ़ायरफ़ॉक्स और सफारी दोनों ही URL में गैर-ASCII वर्ण प्रदर्शित करते हैं , और स्पष्ट रूप से वे बहुत अच्छे लगते हैं। S http://somewhere.com/news/read/ 前 links links links links links links links links links links। 'जैसे लिंक्स का समर्थन करना अच्छा है ।

तो यहाँ कुछ PHP कोड है जो यह करूँगा, लेकिन मैंने इसे लिखा और तनाव का परीक्षण नहीं किया।

<?php
    function slug($str)
    {
        $args = func_get_args();
        array_filter($args);  //remove blanks
        $slug = mb_strtolower(implode('-', $args));

        $real_slug = '';
        $hyphen = '';
        foreach(SU::mb_str_split($slug) as $c)
        {
            if (strlen($c) > 1 && mb_strlen($c)===1)
            {
                $real_slug .= $hyphen . $c;
                $hyphen = '';
            }
            else
            {
                switch($c)
                {
                    case '&':
                        $hyphen = $real_slug ? '-and-' : '';
                        break;
                    case 'a':
                    case 'b':
                    case 'c':
                    case 'd':
                    case 'e':
                    case 'f':
                    case 'g':
                    case 'h':
                    case 'i':
                    case 'j':
                    case 'k':
                    case 'l':
                    case 'm':
                    case 'n':
                    case 'o':
                    case 'p':
                    case 'q':
                    case 'r':
                    case 's':
                    case 't':
                    case 'u':
                    case 'v':
                    case 'w':
                    case 'x':
                    case 'y':
                    case 'z':

                    case 'A':
                    case 'B':
                    case 'C':
                    case 'D':
                    case 'E':
                    case 'F':
                    case 'G':
                    case 'H':
                    case 'I':
                    case 'J':
                    case 'K':
                    case 'L':
                    case 'M':
                    case 'N':
                    case 'O':
                    case 'P':
                    case 'Q':
                    case 'R':
                    case 'S':
                    case 'T':
                    case 'U':
                    case 'V':
                    case 'W':
                    case 'X':
                    case 'Y':
                    case 'Z':

                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        $real_slug .= $hyphen . $c;
                        $hyphen = '';
                        break;

                    default:
                       $hyphen = $hyphen ? $hyphen : ($real_slug ? '-' : '');
                }
            }
        }
        return $real_slug;
    }

उदाहरण:

$str = "~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 コリン ~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 トーマス ~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 アーノルド ~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04";
echo slug($str);

आउटपुट: s リ コ -और- コ コ コ コ -और- ア コ コ コ コ

'-और-' इसलिए है क्योंकि 'और -'-' में बदल जाते हैं।


4
मैं वास्तव में नहीं जानता कि इस जानकारी के बारे में क्या कहना है।
जज 15'12

3
स्विच केस स्टेटमेंट का उपयोग न करने का यह वास्तव में अच्छा उदाहरण है।
निकजी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.