This content originally appeared on DEV Community and was authored by PixelPerfect Pro
You ever try to make your site “global-ready”? yeah, I did once.
I thought: “oh cool, I’ll just add a lang="ar"
and ship it.”
two hours later: my navbar’s on the wrong side, my dates look like lottery numbers, and my boss says:
“hey, users in japan think our deal ends next year. fix it.”
That’s when I realized: css + js intl features are not optional. they’re survival gear.
So here’s my top 16 pain points turned into lessons — with jokes, blood.
1. Margins that betray you — margin-inline
old me:
.card { margin-left: 20px; }
rtl users: “wtf is this spacing?”
new me:
.card { margin-inline: 20px; }
Impression of my old css: “sorry bro, I only work in english.”
mdn: logical props
2. Padding that loves both sides — padding-inline
if you still write padding-left
and padding-right
, you’re that guy at the gym using jeans instead of gym shorts.
don’t be that guy.
3. Vertical writing-mode
.text { writing-mode: vertical-rl; }
good for japanese.
bad for me the first time, because I rotated every div
with transform: rotate(90deg)
.
“look at my app! it’s tetris!”
4. :dir() selector
button:dir(rtl) { transform: rotate(180deg); }
it’s like a lie detector for direction.
“you rtl? i can tell. stop lying.”
5. line-break: loose vs strict
Asian languages don’t use spaces.
So your perfect grid? boom — text exploded like popcorn in a microwave.
6. hyphens: auto
German words are like boss fights.
.text { hyphens: auto; }
without it, your layout screams “nein!”
7. text-transform with respect
Turkish devs still hate me for uppercasing “istanbul” wrong.
İ
vs
I
I learned the hard way.
8. font-variant-east-asian
ever see kana squished like a sandwich?
fix it with this.
p { font-variant-east-asian: ruby; }
9. Unicode-bidi — the nuclear switch
I once mixed hebrew + english in a chat app.
the text looked like my cat walked over the keyboard.
then i found this:
p { unicode-bidi: plaintext; }
instant fix.
10. list-style in other worlds
ul { list-style: arabic-indic; }
arabic numbers.
no more 1. 2. 3. — now it’s culturally correct.
JS Intl — the revenge arc
11. Intl.NumberFormat (aka stop replacing commas like a caveman)
new Intl.NumberFormat("de-DE").format(1234567.89);
// 1.234.567,89
before: I used .replace(".", ",")
.
after: I went to therapy.
12. Intl.DateTimeFormat (dates that don’t start wars)
new Intl.DateTimeFormat("ja-JP", { dateStyle: "full" })
.format(new Date("2025-08-12"));
// 2025年8月12日火曜日
before: everyone thought our sale was in december.
after: we stopped refunding angry users.
13. Intl.PluralRules (no more “1 items”)
const pr = new Intl.PluralRules("ru-RU");
pr.select(3); // "few"
before: I used if (count === 1) ? "item" : "items"
.
russians: laughing at me like eddie murphy.
14. Intl.DisplayNames
new Intl.DisplayNames(["fr"], { type: "language" }).of("fr");
// "français"
before: “Language: fr.”
users: “what the hell is fr? a new crypto coin?”
15. Intl.RelativeTimeFormat
new Intl.RelativeTimeFormat("en", { numeric: "auto" })
.format(-1, "day");
// "yesterday"
before: I wrote “1 days ago.”
qa wrote me up.
16. Intl.Collator (alphabet soup ordering)
["ä", "z"].sort(new Intl.Collator("de").compare);
// ["ä", "z"]
before: I sorted strings with localeCompare
.
after: swedish users stopped emailing me about their alphabet rights.
Grand finale
Look — internationalization is not “advanced.”
It’s survival. it’s respect. It’s the difference between users loving your product… and users thinking your site was made by a drunk raccoon.
CSS logical props + js intl apis = no more pain emails at 3am.
and yes, my hand still hurts, but I’m smiling, because I don’t have to replace(".", ",")
ever again.
This content originally appeared on DEV Community and was authored by PixelPerfect Pro