<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mohammad AlShammari</title>
    <description>The latest articles on DEV Community by Mohammad AlShammari (@imohad).</description>
    <link>https://dev.to/imohad</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3835138%2F85c1bc9d-5fe8-4489-8555-8c8b10802e19.png</url>
      <title>DEV Community: Mohammad AlShammari</title>
      <link>https://dev.to/imohad</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/imohad"/>
    <language>en</language>
    <item>
      <title>RTL Is Not a Translation Problem. It's an Architecture Problem.</title>
      <dc:creator>Mohammad AlShammari</dc:creator>
      <pubDate>Wed, 25 Mar 2026 02:53:22 +0000</pubDate>
      <link>https://dev.to/imohad/rtl-is-not-a-translation-problem-its-an-architecture-problem-4dg4</link>
      <guid>https://dev.to/imohad/rtl-is-not-a-translation-problem-its-an-architecture-problem-4dg4</guid>
      <description>&lt;p&gt;Most software is built in English first. Right-to-left languages — Arabic, Hebrew, Persian, Urdu — are treated as an afterthought.&lt;/p&gt;

&lt;p&gt;This isn't a translation problem. It's an architecture problem.&lt;/p&gt;

&lt;p&gt;When you write &lt;code&gt;margin-left: 16px&lt;/code&gt;, 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.&lt;/p&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Text engine&lt;/strong&gt; — Does it understand BiDi?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direction logic&lt;/strong&gt; — &lt;code&gt;dir="rtl"&lt;/code&gt; and DirectionProvider&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSS layout&lt;/strong&gt; — Physical vs logical properties&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Translations&lt;/strong&gt; — ar.json and i18n config&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hardcoded text&lt;/strong&gt; — Strings buried in JSX&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;That experience led me to build &lt;strong&gt;rtl-first&lt;/strong&gt; — an open source framework with tools for every stage of RTL adoption.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;@rtl-first/codemod&lt;/strong&gt; (v0.2.2 on npm) transforms CSS physical properties to logical ones using a multi-engine architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostCSS AST for CSS files (safe shorthand decomposition)&lt;/li&gt;
&lt;li&gt;jscodeshift AST for JavaScript (CSS-in-JS style objects)&lt;/li&gt;
&lt;li&gt;Tailwind class mapper (ml-4 → ms-4 in className, cn(), clsx())&lt;/li&gt;
&lt;li&gt;Regex fallback (zero dependencies, always available)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Safety built in: &lt;code&gt;left&lt;/code&gt;/&lt;code&gt;right&lt;/code&gt; are excluded from JS transforms (DOM ambiguity), jscodeshift corruption is auto-detected and rolled back, and the output is fully idempotent.&lt;/p&gt;

&lt;p&gt;We tested it on 5 real platforms:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Stars&lt;/th&gt;
&lt;th&gt;Files&lt;/th&gt;
&lt;th&gt;Changes&lt;/th&gt;
&lt;th&gt;Errors&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dify&lt;/td&gt;
&lt;td&gt;133k&lt;/td&gt;
&lt;td&gt;1,049&lt;/td&gt;
&lt;td&gt;3,382&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cal.com&lt;/td&gt;
&lt;td&gt;34k&lt;/td&gt;
&lt;td&gt;452&lt;/td&gt;
&lt;td&gt;1,868&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NocoBase&lt;/td&gt;
&lt;td&gt;15k&lt;/td&gt;
&lt;td&gt;308&lt;/td&gt;
&lt;td&gt;715&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LobeChat&lt;/td&gt;
&lt;td&gt;80k&lt;/td&gt;
&lt;td&gt;139&lt;/td&gt;
&lt;td&gt;214&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Twenty CRM&lt;/td&gt;
&lt;td&gt;34k&lt;/td&gt;
&lt;td&gt;74&lt;/td&gt;
&lt;td&gt;238&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;2,022 files. 6,417 changes. Zero errors.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;NocoBase was migrated for real (not dry-run): 78 files, 164 changes, zero new TypeScript errors, zero corruption, fully idempotent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The full toolkit
&lt;/h2&gt;

&lt;p&gt;8 packages on npm under &lt;code&gt;@rtl-first/*&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;@rtl-first/codemod&lt;/strong&gt; (v0.2.2) — Multi-engine CSS physical→logical transformer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@rtl-first/audit&lt;/strong&gt; — Scans any repo and reports which RTL layers are broken&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@rtl-first/translation-kit&lt;/strong&gt; — Detects missing translation keys between locales&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@rtl-first/contributor-agent&lt;/strong&gt; — Generates ready-to-submit PRs from audit results&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@rtl-first/direction-injector&lt;/strong&gt; — Detects your framework and adds &lt;code&gt;dir="rtl"&lt;/code&gt; to the right file (9 frameworks)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@rtl-first/locale-scaffolder&lt;/strong&gt; — Copies locale files, updates i18n config, generates a LocaleSwitcher component (6 i18n libraries)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@rtl-first/patch-generator&lt;/strong&gt; — Generates rebaseable shell scripts for each RTL layer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@rtl-first/arabize&lt;/strong&gt; — One command runs all three forker tools: "arabize any open source platform"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All packages have zero required dependencies. The codemod has optional peer dependencies (postcss, jscodeshift) for AST mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/imohad" rel="noopener noreferrer"&gt;
        imohad
      &lt;/a&gt; / &lt;a href="https://github.com/imohad/rtl-first" rel="noopener noreferrer"&gt;
        rtl-first
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Build for the world from day one. Framework for RTL support in open-source projects — methodology, tools, and playbooks.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;rtl-first&lt;/h1&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;هذا العمل هديّة لكل ناطق بالعربية
أسأل الله أن يجعله وقفاً لوجهه الكريم، وعلماً يُنتفع به إلى يوم الدين.&lt;/p&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Arabize any JavaScript web application. Build for the world from day one.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Most software is built English-first. RTL languages — Arabic, Hebrew, Persian, Urdu — are treated as an afterthought. &lt;strong&gt;This is not a translation problem. This is an architecture problem.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;rtl-first is an open-source framework and CLI toolkit for arabizing any web application built with JavaScript frameworks. It works on &lt;strong&gt;any project&lt;/strong&gt; 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.&lt;/p&gt;
&lt;p&gt;Three audiences, one framework:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Builders&lt;/strong&gt; — building a new platform RTL-ready from day one&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contributors&lt;/strong&gt; — adding RTL support to open-source projects via upstream PRs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forkers&lt;/strong&gt; — taking any open-source platform and arabizing it for your market&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Quick Start&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Forkers —&lt;/h3&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/imohad/rtl-first" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I'd love to hear from developers working on RTL challenges. What platforms are you trying to arabize? What's the hardest part?&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
      <category>css</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
