feat(tui): RTL/Bidi support for Persian, Arabic, Hebrew, and Urdu text - #41462
feat(tui): RTL/Bidi support for Persian, Arabic, Hebrew, and Urdu text#41462liuhao1024 wants to merge 1 commit into
Conversation
… text Implements Phase 1 (MVP) of RTL support in the TUI transcript: - Add isRtl() utility using first-strong-character heuristic (CSS direction: auto) - Detect RTL text via Unicode code point ranges (Hebrew, Arabic, Persian, Urdu) - Reverse message row layout (flexDirection=row-reverse) for RTL messages - Right-align message content (alignItems=flex-end) for RTL - Mirror gutter glyph to right side for RTL messages - 10 unit tests covering Persian, Arabic, Hebrew, Urdu, mixed text, ANSI stripping Closes NousResearch#41454
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Approved
RTL/Bidi support for Persian, Arabic, Hebrew, Urdu — well-scoped, no elsewhere surface area.
Highlights
isRtlfirst-strong-char detection matches CSSdirection: autosemantics, which is what users expect.- Row flex-direction (
row-reversevsrow) andfromLeftEdgeare flipped by thertlflag — visual layout inverts correctly for RTL.
The change is purely additive in the desktop UI; no gateway or server-side impact.
No issues.
Reviewed by Hermes Agent
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the focused TUI RTL contribution. Current main now performs software bidi reordering in ui-tui/packages/hermes-ink/src/ink/bidi.ts:55-110, but MessageLine still lays out the gutter and body left-to-right (ui-tui/src/components/messageLine.tsx:229-237), so the alignment portion remains useful.
Problems
ui-tui/src/lib/text.ts:382returns on the first non-whitespace code point, not the first strong directional character. Leading punctuation such as(مرحبا)is therefore classified LTR.ui-tui/src/components/messageLine.tsx:244usesalignItemson a default row Box. That aligns the vertical cross-axis, not horizontal body placement; RTL text remains left-aligned inside its body box. Use a main-axis layout property and cover it with a rendered transcript assertion.- The response separator at
ui-tui/src/components/messageLine.tsx:220-228remains left-oriented when an RTL assistant message shows details.
Suggested changes
- Make detection skip neutral characters until a strong RTL/LTR character and add punctuation/numeric-prefix fixtures.
- Add
renderSynccoverage alongsideui-tui/src/__tests__/messages.test.ts:31-72for RTL gutter/body/separator placement.
Automated hermes-sweeper review.
| const cp = clean.codePointAt(i)! | ||
| // Skip whitespace / control chars | ||
| if (cp <= 0x20 || (cp >= 0x09 && cp <= 0x0D)) continue | ||
| return ( |
There was a problem hiding this comment.
This returns for the first non-whitespace character, not the first strong directional character. (مرحبا) and 1. مرحبا therefore classify as LTR. Skip bidi-neutral characters until an RTL or LTR strong character, and add fixtures for those prefixes.
| <Box width={transcriptBodyWidth(cols, msg.role, t.brand.prompt, TERMUX_TUI_MODE)}>{content}</Box> | ||
| <Box | ||
| width={transcriptBodyWidth(cols, msg.role, t.brand.prompt, TERMUX_TUI_MODE)} | ||
| alignItems={rtl ? 'flex-end' : 'flex-start'} |
There was a problem hiding this comment.
The inner Box defaults to flexDirection: 'row', so alignItems controls its vertical cross-axis rather than horizontal text placement. RTL content will remain left-aligned in this fixed-width body Box; use the appropriate main-axis alignment and add a rendered layout assertion.
Summary
Implements Phase 1 (MVP) of RTL/Bidi support in the Hermes TUI, making Persian, Arabic, Hebrew, and Urdu text render correctly for ~500M+ potential users.
Problem
Persian, Arabic, Hebrew, and Urdu text renders left-aligned with disconnected letters in the Hermes TUI (
hermes --tui). This makes the TUI unusable for RTL language users.Changes
ui-tui/src/lib/text.tsisRtl()function using the first-strong-character heuristic (matches CSSdirection: autobehavior)ui-tui/src/components/messageLine.tsxflexDirection="row-reverse"for RTL messages (gutter moves to right side)alignItems="flex-end"for RTL message content (right-aligned)fromLeftEdgefor RTL messages (selection zone follows reversed layout)ui-tui/src/__tests__/text.test.tsTesting
All existing tests continue to pass. No new dependencies.
Closes #41454