Arabic became genuinely reachable in #341 (the UI locale moved to users.locale and every email is translated), but the app has never been exercised right-to-left. The sidebar was visibly broken and is fixed in that PR; the rest of the interface has not been checked.
What was already fixed
resources/js/components/ui/sidebar/Sidebar.vue pinned the sidebar with physical left-0 / right-0 chosen from the side prop. In RTL the document flow inverts but a fixed left-0 does not follow it, so the sidebar overlapped the content and left a dead strip on the other edge. It now uses logical properties — start-0 / end-0, border-e-2 / border-s-2 — which the browser resolves from dir, with no conditional and no change to LTR.
What is left
The same class of bug is spread across the Vue components. Counting only occurrences inside class / :class attributes:
| class |
occurrences |
ml-* |
46 |
pl-* |
16 |
mr-* |
12 |
border-r-* |
6 |
pr-* |
4 |
rounded-l* |
68 |
115 .vue files contain at least one. Not all of them matter — plenty are inside a component whose own layout is symmetric — so this needs a pass with judgement, not a find/replace.
Some are also paired with transforms that need flipping (-ml-6 -translate-x-1 in BrandForm.vue:210), and those do not have a logical equivalent; they need a rtl: variant.
Suggested approach
- Walk the main screens with an Arabic account and note what actually breaks — the count above is surface area, not a defect list.
- Convert what is genuinely directional:
ml-/mr- → ms-/me-, pl-/pr- → ps-/pe-, border-l/border-r → border-s/border-e, rounded-l/rounded-r → rounded-s/rounded-e, left-/right- → start-/end-.
- For transforms and anything without a logical form, use Tailwind's
rtl: variant.
- Cover the layout shell with a browser test in Arabic so it does not regress —
tests/Browser/SidebarLanguageSwitchTest.php already switches to Arabic and asserts dir="rtl", so it is the natural place to extend.
Worth noting the ordering: ContentLanguage::direction() and Locale::direction() already make Arabic the only RTL case, and SetLocale renders htmlDir into the Blade root, so the plumbing is in place — this is purely styling.
Arabic became genuinely reachable in #341 (the UI locale moved to
users.localeand every email is translated), but the app has never been exercised right-to-left. The sidebar was visibly broken and is fixed in that PR; the rest of the interface has not been checked.What was already fixed
resources/js/components/ui/sidebar/Sidebar.vuepinned the sidebar with physicalleft-0/right-0chosen from thesideprop. In RTL the document flow inverts but afixed left-0does not follow it, so the sidebar overlapped the content and left a dead strip on the other edge. It now uses logical properties —start-0/end-0,border-e-2/border-s-2— which the browser resolves fromdir, with no conditional and no change to LTR.What is left
The same class of bug is spread across the Vue components. Counting only occurrences inside
class/:classattributes:ml-*pl-*mr-*border-r-*pr-*rounded-l*115
.vuefiles contain at least one. Not all of them matter — plenty are inside a component whose own layout is symmetric — so this needs a pass with judgement, not a find/replace.Some are also paired with transforms that need flipping (
-ml-6 -translate-x-1inBrandForm.vue:210), and those do not have a logical equivalent; they need artl:variant.Suggested approach
ml-/mr-→ms-/me-,pl-/pr-→ps-/pe-,border-l/border-r→border-s/border-e,rounded-l/rounded-r→rounded-s/rounded-e,left-/right-→start-/end-.rtl:variant.tests/Browser/SidebarLanguageSwitchTest.phpalready switches to Arabic and assertsdir="rtl", so it is the natural place to extend.Worth noting the ordering:
ContentLanguage::direction()andLocale::direction()already make Arabic the only RTL case, andSetLocalerendershtmlDirinto the Blade root, so the plumbing is in place — this is purely styling.