I build products for Hebrew-speaking users. Every time I ask an AI to generate a component, I get the same broken output — margin-left instead of margin-inline-start, ml-4 instead of ms-4, arrows pointing the wrong way, and order numbers jumping around inside RTL sentences.
I fix it. I ask for the next component. Same bugs. The AI doesn't learn — it's trained on LTR codebases and has zero awareness that RTL exists.
After months of manually fixing the same 5-6 patterns in every single component, I built RTLify — a CLI that teaches your AI editor the rules once, so you never fix them again.
npx rtlify-ai init
One command. Works with Claude Code, Cursor, Windsurf, Cline, GitHub Copilot, Gemini CLI, and Codex CLI.
The Bugs AI Keeps Making
Let me show you exactly what goes wrong. If you've built anything in Hebrew, Arabic, Persian, or Urdu — you'll recognize every single one.
1. Physical CSS Instead of Logical
AI writes:
.sidebar {
margin-left: 16px;
padding-right: 8px;
border-left: 1px solid #ccc;
left: 0;
}
In RTL, "left" is "right". The layout mirrors, but these properties don't. The correct version:
.sidebar {
margin-inline-start: 16px;
padding-inline-end: 8px;
border-inline-start: 1px solid #ccc;
inset-inline-start: 0;
}
Logical properties work in both LTR and RTL. AI never uses them unless you tell it to.
2. Wrong Tailwind Classes
This is the most common one. AI writes:
<div className="ml-4 pr-6 text-left border-l-2 rounded-tl-lg">
Every single class here is wrong for RTL. The correct version:
<div className="ms-4 pe-6 text-start border-s-2 rounded-ss-lg">
RTLify includes a full mapping table with 20+ conversions — ml → ms, pr → pe, text-left → text-start, float-right → float-end, rounded-tl → rounded-ss, and more.
3. Numbers Jumping Around (Bidi Text)
This is the sneaky one. Look at this Hebrew sentence:
<p>ההזמנה שלך #12345 אושרה בהצלחה</p>
Looks fine in your code editor. Open it in a browser with dir="rtl" — the number #12345 visually jumps to a completely wrong position. The sentence becomes unreadable.
The fix is a <bdi> tag:
<p>ההזמנה שלך <bdi>#12345</bdi> אושרה בהצלחה</p>
Same applies to phone numbers, dates, English brand names — any LTR content inside an RTL sentence needs <bdi> wrapping. AI never does this.
4. Icons Pointing the Wrong Way
In an RTL interface, a "next" arrow should point left, not right. But AI always generates:
<ChevronRight className="w-5 h-5" />
The fix:
<ChevronRight className="w-5 h-5 rtl:-scale-x-100" />
Non-directional icons (home, settings, search) should NOT be flipped. AI doesn't know the difference — RTLify teaches it which ones to flip.
5. Currency and Dates
AI formats prices like this:
const price = `₪${amount}`; // Wrong — symbol on wrong side
The correct way:
const price = new Intl.NumberFormat('he-IL', {
style: 'currency',
currency: 'ILS',
}).format(amount);
// → "42.90 ₪" — symbol on correct side, RTL mark included
Same for dates — AI defaults to MM/DD/YYYY instead of DD/MM/YYYY with Intl.DateTimeFormat.
6. React Native Gets It Even Worse
On mobile, the same problems exist but with different APIs:
// AI writes:
paddingLeft: 16
left: 0
textAlign: 'left'
// Should be:
paddingStart: 16
start: 0
writingDirection: 'rtl'
Plus you need I18nManager.isRTL for conditional checks and transform: [{ scaleX: I18nManager.isRTL ? -1 : 1 }] for icon flipping.
How RTLify Works
There's no magic and no runtime dependency. Here's what happens when you run npx rtlify-ai init:
It writes
.rtlify-rules.md— a markdown file containing 8 RTL architecture rules with concrete "do this / not that" code examples. This is the full ruleset the AI will follow.It adds a 3-line pointer to your editor's config file (
CLAUDE.md,.cursorrules,.windsurfrules, etc.) that tells the AI: "read.rtlify-rules.mdbefore generating any UI code."For Claude Code users — it installs a global
/rtlifycommand. Just type/rtlifyin Claude Code and it scans, fixes, and verifies your entire project.
That's it. The AI reads the rules on every conversation. No extra prompting needed.
You can open .rtlify-rules.md and read exactly what the AI sees. Full transparency — it's just a markdown file.
The Linter
RTLify also ships with a scanner that catches violations in existing code:
npx rtlify-ai check
src/components/Sidebar.tsx
3 Tailwind Physical
Use logical classes (ms-*, me-*, ps-*, pe-*)
<div className="ml-4 pl-6 text-left">
src/components/OrderCard.tsx
8 Tailwind Physical
Use text-start / text-end
<h2 className="text-left text-xl">פרטי הזמנה</h2>
2 violations across 2 files
Exits with code 1 — plug it into your CI pipeline to catch RTL violations on every PR.
The Fix Command (Cursor, Windsurf, Cline, Copilot)
Claude Code users get the /rtlify slash command. For every other editor:
npx rtlify-ai fix
It generates a ready-to-paste prompt and copies it to your clipboard. Paste it into Cursor, Windsurf, Cline, or any AI editor — it tells the AI to scan, fix, and verify all RTL violations.
The 8 Rules
| # | Rule | What the AI Learns |
|---|---|---|
| 1 | Logical CSS |
margin-inline-start not margin-left
|
| 2 | Tailwind Mapping | 20+ class conversions (ml-* → ms-*) |
| 3 | Icon Flipping |
rtl:-scale-x-100 on directional icons only |
| 4 | BDI Safety |
<bdi> tags for numbers/English in RTL text |
| 5 | Localized Formats |
Intl.NumberFormat('he-IL') for currency & dates |
| 6 | Safe i18n | Respects your i18n setup or lack of it |
| 7 | Complex Components | Carousels, charts, sliders with dir="rtl"
|
| 8 | React Native |
I18nManager.isRTL, paddingStart, writingDirection
|
Try It
npx rtlify-ai init
Then ask your AI to "build a checkout form in Hebrew" or "create a settings screen in Arabic". You'll see the difference immediately.
GitHub: github.com/idanlevi1/rtlify
NPM: npmjs.com/package/rtlify-ai
If you're building for RTL markets — what's the most annoying RTL bug an AI has generated for you? I'd love to hear in the comments.

Top comments (0)