What Footballers’ Names Do to Software
By PlayFutbol Data Team · · 7 min read
For a while this site published a page at /players/luka-modri. Not a typo anyone made by hand — a slug generator ate the ć off the end of Modrić and nobody noticed, because the page rendered perfectly and the build never complained. 107 of our 766 names go through that same machine. Here is what football names do to software, measured rather than recalled.
Two names, three pipelines
A URL slug has to be ASCII, so every football site needs a function that turns Pierre-Emile Højbjerg into something a browser can carry. There are three common ways to write that function and they are not equivalent. The cover chart above runs two names through all three, and it takes two because no single name shows every difference: normalisation rescues Modrić and does nothing at all for Højbjerg.
| Name | Strip only | Decompose, then strip | Substitute first |
|---|---|---|---|
| Pierre-Emile Højbjerg | pierre-emile-hjbjerg | pierre-emile-h-jbjerg | pierre-emile-hojbjerg |
| Wojciech Szczęsny | wojciech-szczsny | wojciech-szczesny | wojciech-szczesny |
| Luka Modrić | luka-modri | luka-modric | luka-modric |
| İlkay Gündoğan | ilkay-gndoan | ilkay-gundogan | ilkay-gundogan |
| Pascal Groß | pascal-gro | pascal-gro | pascal-gross |
| Kenan Yıldız | kenan-yldz | kenan-y-ld-z | kenan-yildiz |
The first column is the one that bites. Delete every character outside a-z0-9 before hyphenating, and the accented letter does not become its plain cousin — it disappears without even leaving a separator: Modrić loses a consonant, Szczęsny loses a vowel, Højbjerg loses the middle of the word. Across the roster that is 107 names, 14.0% of everyone we track.
It reproduces 11 of the 13 broken ids this site actually served, which is as close as the evidence gets. The roster was assembled over several passes, so there was never one tidy culprit function: the Gündoğan id kept a transliterated u while dropping the ğ, and the Zaïre-Emery id lost a real hyphen along with the diaeresis. Neither falls out of the pipeline above.
Why decomposing first fixes almost all of it
Unicode stores most accented letters two ways. é can be a single character, or it can be a plain e followed by an invisible combining acute accent. Normalising to NFD forces the second form, which means you can delete the accents and keep the letters. That one step takes the damage from 107 names down to 5.
It is the 5 survivors that make the point. These letters do not decompose, because they are not a letter plus a mark — they are letters in their own right, with their own place in their alphabet:
øappears 3 times in our names and survives NFD untouched, so a naive strip deletes it outright.ıappears 2 times in our names and survives NFD untouched, so a naive strip deletes it outright.ßappears 1 time in our names and survives NFD untouched, so a naive strip deletes it outright.
Danish ø is not an o wearing a stroke; it sits separately in the Danish alphabet, after æ. Turkish has two distinct letters, dotted i and dotless ı, and they are not interchangeable. German ß expands to two letters, not one. No amount of normalisation will guess any of that; it takes an explicit table, which is the third column.
107
names broken
Drop non-ASCII, then hyphenate
How the bug usually gets written
5
names broken
Decompose first, then strip
NFD, drop combining marks
0
names broken
Substitute, decompose, strip
Plus an explicit letter table
The same 766 names through each pipeline. Only the third gets every one right.
33 characters, and English uses none of them
Our 766 names contain 33 distinct non-ASCII characters. They are not spread evenly, and that is the part worth dwelling on.
Squads by the share of their names carrying a diacritic, for nationalities with at least twelve players in the database.
DEU tops it at 26% (13 of 50). The ENG squad sits at zero — not one accented character across 82 names.
That zero is the whole explanation for how a bug like this ships. Write the slug function, test it on the English squad, watch every case pass. The failing inputs are all in the columns you did not look at. Our version survived in production for months and was eventually caught not by a test but by someone reading a URL.
The characters, by how often they turn up
The highlighted ones are the 3 that normalisation cannot help with. Everything else is a letter with a mark on top, and NFD will separate the two for you.
What we actually broke, and what it cost
13 player URLs on this site were misspellings of the player’s own name. They were built, indexed and linked from our own club pages. The fix was not just renaming them: photos are looked up by the same id, so the rename silently dropped those players to a placeholder image until the files were moved too — a failure with no error message anywhere, since the page still rendered.
The corrected pages now live at Alexander Sørloth, Kenan Yıldız, Pascal Groß and the rest, with every old URL permanently redirected so nothing that linked to the broken spelling is lost.
Stripping the mark also strips the pronunciation
A slug is a compromise and everyone accepts it: nobody minds that /players/rasmus-hojlund is not quite the player’s name. It only has to be stable, readable and unique.
The trouble starts when that flattened string escapes the URL bar. Those marks are not decoration — they are pronunciation instructions, and they are usually the only ones a name carries. Danish ø is a rounded front vowel with no English equivalent; writing Hojlund does not approximate it, it replaces it with a different vowel entirely. Turkish dotless ı and dotted i are separate sounds. Nothing about Gundogan tells a reader that the ğ lengthens the vowel before it rather than being pronounced at all.
This is where it stops being a database problem and becomes an audio one. Anything that reads text aloud — a screen reader, an accessibility layer, a text-to-speech tool — says what it is given, so a name that lost its diacritics upstream is a name that will be mispronounced downstream, every time, with no way for the engine to know. If you want to hear the difference the marks make, the test is simple: feed one of these names in both spellings and listen to what changes.
Which is a decent argument for keeping the accented form as the display name even when the slug cannot have it. We store both: the URL is ASCII, the name on the page is spelled the way the player spells it. That is not a nicety. Getting somebody’s name right is the smallest possible courtesy, and a database that quietly deletes a letter from it has already failed at the easy part.
How this was built
Every figure here comes from running the three slug functions over the live roster at build time, not from a record of what went wrong. The character counts, the 107 and the 5, and each worked example are all measured on the same 766 names the rest of the site uses. Nationality rows are limited to squads of at least twelve players, because a percentage over five names is not a pattern.
Play with the same data
Every name in that table is searchable in the games. If you want to find out whether you can spell them as well as you can recognise them, Futbol Wordle makes you type one out, Who Am I? reveals a player through six clues, and Guess the Nationality turns the pattern in this article into the actual puzzle.
About this article
Written by the PlayFutbol Data Team. Figures are computed at build time from our player database, which is reconciled against Wikidata and cross-checked with Transfermarkt and club pages. When a claim is not supported by the data, we say so in the text rather than leaving it out.