هذا المقال متوفر باللغة العربية — اقرأ بالعربية
Arabic sites break in small, annoying ways: an arrow points the wrong way, a phone number shows up backwards, an order email arrives aligned to the left, or a post title turns into a row of question marks. This guide shows you how to fix WordPress RTL issues one by one, starting with how WordPress decides a page is right-to-left, then moving through CSS, mixed Arabic and English text, fonts, digits, forms, emails, slugs and the database. Each section explains the cause, so you fix the problem once instead of patching it on every page.
How WordPress handles right-to-left languages
Before touching any CSS, it helps to know what WordPress already does for you. Most RTL bugs come from a theme or plugin that ignores these built-in tools.
The is_rtl() check
WordPress has a function called is_rtl() that returns true when the current locale is right-to-left, as Arabic is. Core uses it in many places. For example, get_language_attributes() uses it to print dir="rtl" on the <html> tag, and get_body_class() uses it to add an rtl class to the body. If your theme calls language_attributes() and body_class() in its header, the browser gets the correct direction for the whole page.
One detail that confuses people: the locale can differ between the front end and the dashboard. WordPress has a site language (what visitors see) and a user language (what you see in the admin, set in your profile). If your profile is in English and the site is in Arabic, the editor runs left-to-right for you while visitors see right-to-left.
rtl.css and the theme’s RTL stylesheet
WordPress looks in the active theme’s folder for a stylesheet named after the locale, such as ar.css, and if that doesn’t exist it looks for a file named after the text direction, which for Arabic is rtl.css. It prints that file in the page head automatically. A child theme loads its own rtl.css, not the parent’s, so if you build a child theme for an Arabic site and the layout suddenly breaks, a missing RTL file is the first thing to check.
For stylesheets you enqueue yourself, the cleaner method is wp_style_add_data() with the rtl key. Setting it to 'replace' tells WordPress to load style-rtl.css instead of style.css when the locale is RTL. Setting it to true loads the RTL file in addition to the main one.
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_style( 'mytheme-style', get_stylesheet_uri() );
wp_style_add_data( 'mytheme-style', 'rtl', 'replace' );
} );
Remember to place style-rtl.css next to style.css. Many developers generate it automatically from the main stylesheet with a tool such as RTLCSS, then fix the few rules that shouldn’t flip.
Use CSS logical properties instead of left and right
The biggest source of RTL bugs is CSS written with physical directions: margin-left, padding-right, float: left, text-align: left. Those values mean the same thing in every language, so an icon that should sit before a heading in Arabic ends up after it.
CSS logical properties, documented on MDN, describe positions relative to the writing direction instead. margin-inline-start is the left margin in English and the right margin in Arabic. text-align: start aligns to the right in an RTL page. The W3C internationalization guidance recommends the same approach: set direction with the dir attribute, and use start and end in your CSS.
/* Before: breaks in Arabic */
.card-icon { margin-right: 12px; text-align: left; }
/* After: works in both directions */
.card-icon { margin-inline-end: 12px; text-align: start; }
Useful replacements to remember:
margin-leftandmargin-rightbecomemargin-inline-startandmargin-inline-end.padding-leftandpadding-rightbecomepadding-inline-startandpadding-inline-end.leftandrightin positioning becomeinset-inline-startandinset-inline-end.text-align: leftbecomestext-align: start.border-leftbecomesborder-inline-start.
Flexbox and grid already follow the writing direction, so a row of items reverses on its own in an Arabic page. If you see a menu or a card grid that refuses to flip, look for a hard-coded flex-direction: row-reverse or an absolute position using left.
Mixed Arabic and English text: dir, bdi and unicode-bidi
Arabic content is full of English words, product codes, prices, emails and URLs. The browser uses the Unicode bidirectional algorithm to order them, and it usually gets it right. It goes wrong when an English phrase starts or ends with punctuation or a number, or when one English phrase is followed by another.
The W3C guidance is simple:
- Set the page direction once with
dir="rtl"on the<html>tag. WordPress does this for you if the theme is coded properly. - When you know a phrase is in the opposite direction, wrap it tightly in an element with its own
dir, for example<span dir="ltr">. - When the text comes from users or the database and you don’t know its direction, wrap it in
<bdi>or adddir="auto". The browser then isolates it and picks a direction from the first strong character.
<p>رقم الطلب: <bdi>WC-1045</bdi></p>
<p>تابعنا على <span dir="ltr">@heshamsaad</span> للمزيد</p>
What about the CSS unicode-bidi property? MDN warns that it’s meant for document type designers, and that web authors shouldn’t override it. The W3C also advises against setting base direction with CSS. Use the HTML attributes first, and keep unicode-bidi for rare cases where you can’t change the markup.
Icons and arrows: what should mirror and what shouldn’t
Not every icon should flip in Arabic. Mozilla’s RTL guidelines for Firefox give a practical list, and it matches what most design systems recommend:
- Mirror: back and forward arrows, next and previous buttons, progress bars, and icons that show text direction or the position of a sidebar.
- Don’t mirror: checkmarks, the close X, star icons, logos, icons that contain text or numbers, and video or audio player controls. A play button points the same way everywhere.
If your theme uses an icon font or SVG arrows, a single rule using the body class WordPress adds is usually enough:
.rtl .icon-arrow-next,
.rtl .icon-arrow-prev {
transform: scaleX(-1);
}
Check sliders and carousels too. Many slider scripts have their own RTL option that has to be switched on, otherwise slides move in the wrong direction even when the arrows look correct.
Arabic web fonts and font loading
A wrong font causes more than looks. If the theme’s font has no Arabic glyphs, the browser falls back to a system font, so headings and body text can appear in different typefaces. Pick a font family that actually covers Arabic and use it for both headings and body.
Since WordPress 6.5, the Font Library lets you upload font files or install Google Fonts so that the files are hosted on your own site instead of loaded from Google. According to the WordPress documentation, starting in 7.0 it’s available for classic themes as well as block themes, under Appearance > Fonts.
If you load fonts manually, keep it light:
@font-face {
font-family: "Cairo";
src: url("/wp-content/uploads/fonts/cairo-arabic.woff2") format("woff2");
font-weight: 400;
font-display: swap;
unicode-range: U+0600-06FF, U+0750-077F, U+FB50-FDFF, U+FE70-FEFF;
}
The font-display: swap value, documented on MDN, shows text immediately with a fallback font while the web font loads. The unicode-range covers the main Arabic Unicode blocks, so the file only downloads when Arabic text is on the page. Font weight and loading also affect speed; we cover that in detail in our guide to speeding up Arabic WordPress sites.
Arabic digits versus Western digits
Arabic-Indic digits (٠١٢٣٤٥٦٧٨٩) are different Unicode characters from Western digits (0123456789). They look like numbers to people, but to code they are not the same thing. That causes real problems:
- A visitor types a phone number on a mobile keyboard set to Arabic, and a validation rule that expects 0 to 9 rejects it.
- A coupon code or order number typed in Arabic digits doesn’t match the one stored in the database.
- The same page shows prices in one style and dates in another, which looks careless.
Pick one style for display and stick to it across the site. For input, accept both and convert to Western digits before you validate or save:
function hs_normalize_digits( $value ) {
$arabic = array( '٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩' );
$western = array( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' );
return str_replace( $arabic, $western, $value );
}
Forms and input direction
When the page is RTL, every input field starts typing from the right. That’s right for a name or a message, but awkward for an email address, a URL or a phone number, where the cursor and punctuation jump around while the visitor types.
<input type="email" name="email" dir="ltr">
<input type="tel" name="phone" dir="ltr">
<textarea name="message" dir="auto"></textarea>
Set dir="ltr" on fields that are always Latin, and dir="auto" on free text fields so each paragraph takes the direction of what the visitor writes. The W3C also documents a dirname attribute that sends the detected direction to the server along with the form data, which is handy if you store messages in both languages. Most form plugins let you add a custom class or attribute per field; if yours doesn’t, a small script or CSS on the field is the fallback.
Page builder RTL quirks
Page builders add their own layer. Each builder handles RTL differently, so test on your setup rather than assuming. The issues we see most often:
- Spacing set as separate top, right, bottom and left values that don’t flip in the Arabic version.
- Text alignment set to left on individual widgets, which overrides the page direction.
- Custom CSS added in the builder using physical properties.
- Add-on packs that load their own sliders or icon sets without RTL support.
In the block editor, when your dashboard language is RTL, the paragraph block toolbar shows a “Left to right” button. It sets the block’s direction attribute, which is the clean way to add an English paragraph inside an Arabic post.
Emails that render left-to-right
Order emails are a classic complaint: the site is Arabic, but WooCommerce emails arrive aligned to the left with punctuation in the wrong place. In current WooCommerce versions, the email header template uses is_rtl() to set dir on the email wrapper, and the email styles flip alignment and padding the same way. So when emails come out LTR, the cause is usually one of these:
- Outdated template overrides. The theme has copies of WooCommerce email templates in
yourtheme/woocommerce/emails/that predate RTL handling. WooCommerce flags outdated overrides in its System Status report. - The wrong locale at send time. If the email is generated while WordPress is running in an LTR language,
is_rtl()returns false. Check the site language and the language of the admin account that triggers the email. - A plugin that builds its own emails without any direction setting. Contact forms and booking plugins are common examples.
Send a test order to yourself and open it in Gmail and on a phone, since email clients strip some styles.
Arabic slugs and percent-encoding
WordPress allows Arabic slugs. Behind the scenes, sanitize_title_with_dashes() converts each Arabic letter to its percent-encoded form, so a slug is stored as something like %d8%b5%d9%8a%d8%a7%d9%86%d8%a9. Browsers show the Arabic letters in the address bar, but when the link is copied into some apps or emails it appears as the long encoded string.
There’s also a length limit. WordPress caps the encoded slug at 200 characters, and each Arabic letter takes six of them, so a long Arabic title gets cut off after a little over 30 letters. Keep Arabic slugs short and meaningful, or use a short English slug for the Arabic version. Whatever you choose, decide before publishing, because changing a slug later breaks old links unless you add a redirect.
Question marks instead of Arabic letters: the database charset
If Arabic text shows as ????, the letters were saved through a connection or into a column that couldn’t store them. WordPress moved to the utf8mb4 character set in version 4.2, and the default wp-config-sample.php sets it:
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );
To see what your tables actually use, run this in phpMyAdmin or the command line:
SELECT TABLE_NAME, TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_database_name';
Two different symptoms need different fixes. Question marks usually mean the original letters were replaced when saved, and converting the table won’t bring them back, so you need a clean backup or re-entry. Garbled characters such as ال usually mean the text was encoded twice during an import or migration, which can often be repaired with a careful export and re-import. In both cases take a full backup first. If the site went down during a migration, our guide to fixing common WordPress errors covers the database connection side.
Multilingual plugins and direction per language
On a site with Arabic and English, direction has to switch with the language. Polylang, for example, stores a text direction for each language, and that setting is what tells WordPress and the theme to load RTL styles. If one language shows the wrong direction, open the language settings in your multilingual plugin and check the direction value before you touch any CSS. Also confirm that the theme has an RTL stylesheet, because the plugin can only switch direction; it can’t write the RTL styles for you.
How to fix WordPress RTL issues: symptom, cause and fix
| Symptom | Likely cause | Fix |
|---|---|---|
| Whole layout is left-aligned | Theme doesn’t output language_attributes(), or the locale isn’t Arabic |
Check the site language and the theme header |
| Layout broke after switching to a child theme | Child theme has no rtl.css |
Add an RTL file to the child theme or load the parent’s |
| Icons sit on the wrong side of text | Physical CSS such as margin-left |
Switch to logical properties |
| Arrows point the wrong way | Directional icons not mirrored | Flip them with .rtl and scaleX(-1) |
| Phone numbers or codes appear scrambled | Unisolated LTR text inside RTL | Wrap in bdi or dir="ltr" |
| Phone field rejects valid numbers | Arabic-Indic digits in input | Normalize digits before validation |
| Order emails are left-aligned | Outdated template overrides or LTR locale at send time | Update overrides, check locale |
| Arabic shows as question marks | Non utf8mb4 table or connection | Fix charset, restore from backup |
| Arabic slugs cut off | 200 character encoded limit | Use shorter slugs |
| Mixed fonts on one page | Font without Arabic glyphs | Use a family that covers Arabic |
RTL testing checklist
- Open the home page, a post, a product and the checkout in Arabic on a phone and a desktop.
- Check that the
<html>tag hasdir="rtl"andlang="ar". - Look for icons, arrows and sliders moving the wrong way.
- Type an email, a phone number in Arabic digits and a mixed message into every form.
- Place a test order and read the emails in at least two email apps.
- Paste a few Arabic page links into WhatsApp and an email to see how the slugs look.
- Save a post with Arabic and an emoji in the title to confirm the database stores four-byte characters.
- Switch languages on a multilingual site and confirm the direction changes each time.
- Repeat the checklist after every theme or page builder update.
Frequently asked questions
Do I need a special Arabic theme?
No. Any well-built theme that ships an RTL stylesheet, or is written with logical properties, works in Arabic. Before you buy a theme, switch a test site to Arabic and look at the demo pages, including the shop and checkout.
Can a plugin fix all RTL problems automatically?
Not really. A plugin can add RTL styles to common elements, but it can’t know how your custom sections, widgets or builder layouts should look. Fixing the theme’s CSS once is more reliable than layering overrides.
Should my Arabic pages use Arabic or English slugs?
Both work for visitors and search engines. Arabic slugs are readable in the address bar but long when shared, while English slugs are short but don’t match the page language. Choose one approach, keep slugs short, and don’t change them after publishing without redirects.
Why does the dashboard look different from the live site?
Because WordPress lets each user pick their own admin language. If your profile is in English, the dashboard and editor are left-to-right even though visitors see the Arabic, right-to-left site.
A final word
Most RTL problems come from a short list of causes: physical CSS, missing RTL stylesheets, unisolated mixed text and settings that don’t follow the site language. Fix the cause and the same bug stops showing up on every new page. If you’d rather have someone keep an eye on this for you, our SiteCare plan covers ongoing fixes and checks for WordPress sites, or you can book a free consultation and we’ll look at your Arabic site together.
References
- is_rtl(), WordPress Developer Resources
- wp_style_add_data(), WordPress Developer Resources
- get_locale_stylesheet_uri(), WordPress Developer Resources
- CSS logical properties and values, MDN
- Structural markup and right-to-left text in HTML, W3C
- Inline markup and bidirectional text in HTML, W3C
- unicode-bidi, MDN
- RTL Guidelines, Firefox Source Docs
- The Font Library, WordPress Documentation
- Template structure and overriding templates, WooCommerce Developer Docs
- The utf8mb4 Upgrade, Make WordPress Core
- How to configure the languages, Polylang