Commit Graph
8 Commits
Author SHA1 Message Date
xhzeemandLinus Rath 23a017d4b7 fix(rtl): set dir=ltr on identity <option> elements
The From-identity picker in the composer and the template form use a
native <select>, so the earlier <bdi> fix can't apply there - browsers
render <option> as plain text and strip any nested markup. The native
OS-rendered option list still respects the dir attribute directly
though, so setting dir="ltr" on each option fixes the same bracket-
mirroring bug for "Name <email>" entries in that native popup.
2026-07-21 23:08:02 +02:00
xhzeemandLinus Rath c7250dc921 fix(rtl): isolate Latin address text ("Name <email>") from RTL bidi reordering
Unicode's bidi algorithm treats < and > as mirrored characters. When a
plain "Name <email>" string is rendered as a text node inside an
RTL-inherited container, the browser swaps and reorders those brackets
for the whole run, producing garbled output (e.g. "<Maria Lopez
<maria.lopez@company.example" instead of "Maria Lopez
<maria.lopez@company.example>").

Wrapped the affected text in native <bdi>, which auto-detects its own
paragraph direction from its content rather than inheriting the
ancestor's - so a Latin address renders LTR and a genuinely
Arabic/Hebrew/Farsi name still renders RTL, both correctly, in:
- recipient-popover.tsx (shared by the email viewer's From/To/Cc/Bcc
  detail rows and the calendar invitation banner's organizer row)
- email-composer.tsx's read-only From display
- eml-preview.tsx's From/To header lines

Left the equivalent <select><option> cases (composer identity picker,
template identity picker) and the composer's quote-header text (which
becomes actual email body content, already isolated per-paragraph by
the existing TextDirection tiptap extension) out of scope - both need
a different fix approach than <bdi>.
2026-07-21 23:08:02 +02:00
xhzeemandLinus Rath 80f76abc38 fix(rtl): flip JS-positioned popovers (storage, logout, account switcher, calendar picker)
These popovers are portaled and positioned via inline styles computed
from getBoundingClientRect() rather than Tailwind classes, so the
logical start-0/end-0 fix doesn't reach them. They always anchored to
the physical right of their trigger (rect.right + 8), which in RTL
pushes them further into the edge the trigger is already flush against
instead of toward the visible content area.

Added isDocumentRTL() to i18n/direction.ts and used it to mirror the
computed position in:
- navigation-rail.tsx: storage quota popover, logout/switch-account menu
- account-switcher.tsx: both the rail and expanded-sidebar variants
- calendar-invitation-banner.tsx: the "add to calendar" picker
2026-07-21 23:08:02 +02:00
xhzeemandLinus Rath adb8686293 fix(rtl): anchor floating menus with logical start/end instead of left/right
Popovers and dropdown menus across the app (sub-address helper, calendar
toolbar/color pickers, contact/template/attachment menus, rich text editor
color and table pickers, unsubscribe confirmation, composer send menu)
were anchored with physical `left-0`/`right-0`. In RTL locales those
don't flip with the trigger, so the menu detaches from the button that
opened it. Switched to Tailwind's logical `start-0`/`end-0` (and the
matching `rounded-s-*`/`rounded-e-*` corners on hover-action overlays)
so they mirror correctly for RTL locales (ar, he, fa) while staying
identical in LTR.
2026-07-21 23:08:02 +02:00
xhzeemandLinus Rath d531ad1930 fix(i18n): register ar messages in the client IntlProvider
components/providers/intl-provider.tsx keeps its own static ALL_MESSAGES
map separate from i18n/request.ts's server-side loader. It was missed
when ar was added, so switching to Arabic flipped to RTL (direction.ts
knew about ar) but rendered English text (messages lookup fell through
to the en fallback).
2026-07-21 23:07:40 +02:00
xhzeemandLinus Rath 953355d2a5 fix(i18n): use UAE flag instead of Saudi flag for ar locale 2026-07-21 23:07:40 +02:00
xhzeemandLinus Rath 8155f98a28 fix(i18n): use Saudi flag instead of pan-Arab colours for ar locale 2026-07-21 23:07:40 +02:00
xhzeemandLinus Rath fda898fc96 feat(i18n): add full Arabic (ar) translation
Adds a complete Arabic locale (2759 keys, full parity with en) and wires
it into routing, RTL direction detection, message loading, the language
switcher, and flag icons alongside the existing he/fa RTL locales.
2026-07-21 23:07:40 +02:00