From a headline to a URL
A slug generator has one job with several awkward corners: take a human title, keep the part a machine can put in a URL, and lose nothing that mattered. Paste a headline above and you get the slug, plus what it cost — how many words survived, how many stop words were dropped, and how many characters had no Latin equivalent at all.
The pipeline is short and the order is deliberate. An explicit table runs first, then Unicode
decomposition removes accents, then everything outside a–z and 0–9 becomes a separator boundary.
Do those two steps in the other order and German breaks.
Accents are the easy half
Crème brûlée becomes creme-brulee through a property of Unicode rather than a lookup table: in
the decomposed form, è is the letter e followed by a separate combining grave accent, so deleting
every combining mark leaves clean ASCII behind. One normalize('NFD') and one regular expression
handle French, Spanish, Portuguese, Polish diacritics and most of Vietnamese.
Then there are the letters that do not decompose, because the mark is part of the letter's design
rather than something added to it. ß, æ, œ, ø, đ, ð, þ, ł, ħ, ı and ŋ all
return unchanged from decomposition, and a slugifier that only strips marks silently deletes them:
Straße becomes strae and Þór becomes r. Those eleven letters, plus seven currency and
operator symbols that read better as words, are handled by an eighteen-entry table applied before
anything else. 100% becomes 100-percent rather than 100.
The part nobody transliterates honestly
Chinese, Japanese, Korean, Cyrillic, Greek, Arabic and Hebrew are not handled, and the tool says so with a count rather than pretending. This is a deliberate limit, not an omission.
Romanising those scripts is a linguistic decision, not a character mapping. Japanese needs to know where words start and which reading a kanji takes in this particular compound — 東京 is Tokyo, but the same second character is kyō or miyako elsewhere. Cyrillic has at least four competing standards that disagree about the same letters, and a Russian reader will judge the result. Producing something plausible and wrong is worse than producing nothing, because nobody checks a slug that looks fine.
For those languages, write the slug by hand — or use the percent-encoded native text, which modern browsers display correctly in the address bar and search engines have handled for years.
Length, stop words and the honest trade
Two options here shorten the slug, and both cost something.
Dropping stop words removes thirty common English function words. It usually reads better, and it occasionally changes meaning: negations and short prepositions carry more weight in a headline than a generic list can know. If every word in the title is a stop word, nothing is removed at all — an empty slug is worse than a plain one.
The length limit cuts on a word boundary rather than mid-word, so a sixty-character limit produces a
slug of fifty-something rather than one ending in configur. If the first word alone exceeds the
limit it is kept whole, because a truncated first word makes the URL unreadable and saves nothing
worth having.
Naming a variable rather than a page? The case converter produces kebab-case without folding accents or dropping words, which is what you want for a CSS class. For measuring the title itself before you publish it, there is the word counter.