Most software is built in English first. Right-to-left languages — Arabic, Hebrew, Persian, Urdu — are treated as an afterthought.
This isn't a translation problem. It's an architecture problem.
When you write margin-left: 16px, you're not just styling — you're encoding a directional assumption into your codebase. Multiply that across thousands of files, and you have an application that fundamentally doesn't work for 400+ million Arabic speakers.
I spent months contributing RTL support to open source platforms like AFFiNE (65k stars), and learned a painful lesson: most platforms have RTL issues buried across five distinct layers:
- Text engine — Does it understand BiDi?
-
Direction logic —
dir="rtl"and DirectionProvider - CSS layout — Physical vs logical properties
- Translations — ar.json and i18n config
- Hardcoded text — Strings buried in JSX
Fixing one layer without understanding the others leads to PRs that get rejected — like mine did on AFFiNE's blocksuite, where the maintainer correctly pointed out that CSS fixes alone can't bring native RTL support to an editor.
That experience led me to build rtl-first — an open source framework with tools for every stage of RTL adoption.
What it does
@rtl-first/codemod (v0.2.2 on npm) transforms CSS physical properties to logical ones using a multi-engine architecture:
- PostCSS AST for CSS files (safe shorthand decomposition)
- jscodeshift AST for JavaScript (CSS-in-JS style objects)
- Tailwind class mapper (ml-4 → ms-4 in className, cn(), clsx())
- Regex fallback (zero dependencies, always available)
Safety built in: left/right are excluded from JS transforms (DOM ambiguity), jscodeshift corruption is auto-detected and rolled back, and the output is fully idempotent.
We tested it on 5 real platforms:
| Platform | Stars | Files | Changes | Errors |
|---|---|---|---|---|
| Dify | 133k | 1,049 | 3,382 | 0 |
| Cal.com | 34k | 452 | 1,868 | 0 |
| NocoBase | 15k | 308 | 715 | 0 |
| LobeChat | 80k | 139 | 214 | 0 |
| Twenty CRM | 34k | 74 | 238 | 0 |
2,022 files. 6,417 changes. Zero errors.
NocoBase was migrated for real (not dry-run): 78 files, 164 changes, zero new TypeScript errors, zero corruption, fully idempotent.
The full toolkit
8 packages on npm under @rtl-first/*:
- @rtl-first/codemod (v0.2.2) — Multi-engine CSS physical→logical transformer
- @rtl-first/audit — Scans any repo and reports which RTL layers are broken
- @rtl-first/translation-kit — Detects missing translation keys between locales
- @rtl-first/contributor-agent — Generates ready-to-submit PRs from audit results
-
@rtl-first/direction-injector — Detects your framework and adds
dir="rtl"to the right file (9 frameworks) - @rtl-first/locale-scaffolder — Copies locale files, updates i18n config, generates a LocaleSwitcher component (6 i18n libraries)
- @rtl-first/patch-generator — Generates rebaseable shell scripts for each RTL layer
- @rtl-first/arabize — One command runs all three forker tools: "arabize any open source platform"
All packages have zero required dependencies. The codemod has optional peer dependencies (postcss, jscodeshift) for AST mode.
Why this matters
Every major open source platform — Dify, AppFlowy, Cal.com, NocoBase — has open issues asking for RTL support. Most are labeled "not planned" or sit unanswered for years.
rtl-first gives developers the tools to either contribute upstream or fork and arabize on their own. If a platform won't support RTL, someone else will.
imohad
/
rtl-first
Build for the world from day one. Framework for RTL support in open-source projects — methodology, tools, and playbooks.
rtl-first
هذا العمل هديّة لكل ناطق بالعربية أسأل الله أن يجعله وقفاً لوجهه الكريم، وعلماً يُنتفع به إلى يوم الدين.
Arabize any JavaScript web application. Build for the world from day one.
Most software is built English-first. RTL languages — Arabic, Hebrew, Persian, Urdu — are treated as an afterthought. This is not a translation problem. This is an architecture problem.
rtl-first is an open-source framework and CLI toolkit for arabizing any web application built with JavaScript frameworks. It works on any project using Next.js, Nuxt, Remix, Vite, Angular, SvelteKit, or Create React App — whether it's an AI platform, a CRM, a scheduling tool, or anything in between.
Three audiences, one framework:
- Builders — building a new platform RTL-ready from day one
- Contributors — adding RTL support to open-source projects via upstream PRs
- Forkers — taking any open-source platform and arabizing it for your market
Quick Start
Forkers —
…I'd love to hear from developers working on RTL challenges. What platforms are you trying to arabize? What's the hardest part?
Top comments (0)