I added platform badges to the project cards on this site: iOS · Android · Web. The badges use the same styling as everything else on the page — small monospace, uppercased:
text-transform: uppercase;
What came out was:
İOS · ANDROİD · WEB
The browser is not wrong
The page is <html lang="tr">. CSS uppercasing applies the casing rules of the text’s language, and in Turkish the capital of i is İ — with the dot. Turkish also has a dotless ı whose capital is I: four letters, two pairs.
So iOS becomes İOS and Android becomes ANDROİD. For a Turkish word that is correct. For a brand name it is not.
Every other badge on the page was a Turkish word — MOBİL + WEB, OYUN, WEB SİTESİ — and all of them came out right. Only the badge carrying a brand name broke, and at small monospace sizes the difference between İOS and IOS is a single dot.
The fix
There are two routes:
text-transform: none, and write the text the way you want it. That is what I chose: the badges now readiOS · Android · Web. Brand names already carry their own casing; not destroying it is the more correct answer.- Put
lang="en"on the element. The transform then uses English rules and yieldsIOS. Technically correct, semantically a lie — that element is not English, it is a brand name.
⚠️ Writing the text as IOS and keeping uppercase also works (in Turkish the capital of I is still I), but then you are the one mangling the brand name.
The same rule bites elsewhere
- JavaScript.
'i'.toUpperCase()always returns'I'— JS is locale-insensitive by default. But'i'.toLocaleUpperCase('tr')returns'İ'. So CSS and JS can uppercase the same string differently. - Search and comparison. A user typing
istanbuland a database holdingİSTANBULmay not match once lowercased on a system with a Turkish locale. The classic “Turkish I problem”. - Database collation. If the server’s locale differs from the app’s, the same query returns different results in two environments.
What to take from it
- Never
text-transforma brand name. Its casing is part of the data, not of the presentation. - The
langattribute is not cosmetic. Casing, hyphenation and screen-reader pronunciation all read it; it needs to be correct, and being correct is what produces surprises like this. - Eyeball uppercase transforms in Turkish interfaces. Especially on English words containing an
i.