You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Two threads here already ask for right-to-left rendering:
#4009 ships a dir="auto" patch as a ZIP plus a Windows batch installer and asks the maintainers to adopt dir="auto" in the core components.
#696 reports that Hello كيف حالك اليوم renders unreadably, traces it to UAX #9 first-strong direction detection, and proposes counting strong characters across the whole string instead.
Both are about direction. Neither translates a string, and nothing upstream implements either. I built the other half — an Arabic language pack — and the direction mechanism it needs, and it runs on a fork branch today.
@deepseek-ai/dsh-client-locale-ar: one in-tree client plugin, 34 dictionary files, about 1060 keys, one file per namespace. Each dictionary is declared satisfies Record<XxxKey, string> against the key union imported type-only from the owning package, so a key added to zh without an Arabic counterpart fails the pack's typecheck rather than showing a missing string at runtime. The plugin registers addLanguage({ id: 'ar', label: 'العربية', fallback: 'en', direction: 'rtl' }) and each namespace as owned effects; an unresolved key falls to English, never to Chinese. It mounts in the web-app bundle roster, so Arabic is selectable in Settings without an install step.
The direction decision, and why it is not html[dir]
The frame does not move. direction: rtl on the document reorders flex and grid children, which relocates the settings navigation, the row controls, and every icon that sits beside its label — a bilingual reader would meet a different application in each language, and every chrome screenshot would change.
Instead the locale plugin publishes the active language's reading order as data-dsh-text-direction on the root and never writes html[dir]. ui-theme owns a single rule: elements a component marks data-dsh-text-zone take text-align: right while Arabic is active. 18 zone markers cover the transcript, composer, settings panels, sidebar lists, and the modal, toast, tooltip, and menu bodies. Two things opt back out:
Content pinned dir="ltr" — code blocks, terminal output, diffs, JSON trees, read blocks — where column order carries meaning.
Authored text marked data-dsh-text-auto, which takes dir="auto" with unicode-bidi: plaintext, so an Arabic reply lands on the right and an English one on the left inside the same transcript.
Component stylesheets that render inside a zone migrated from physical inline-axis properties to logical ones, and a stylesheet spec built on the existing scanner rejects a physical declaration added back to a zone package. Logical properties render identically left-to-right, so the existing en-US goldens are the regression proof.
The dir="auto" plus unicode-bidi: plaintext above resolves each paragraph from its first strong character — exactly the rule #696 reports as unreadable when a sentence opens with an English word. The alternative, counting strong characters across the whole string, decides per paragraph but can flip a paragraph's direction while it is being typed. I chose the standard rule and recorded the tension rather than hiding it; if maintainers prefer the dominant-direction detector, it swaps in behind the same data-dsh-text-auto marker without touching the pack or the zone rule.
Same intent, different delivery. #4009 applies dir="auto" broadly through a patch file users re-apply after every update. Here the same attribute is authored in the components, alignment is a theme-owned rule rather than a per-element attribute, and code and terminal output are explicitly excluded, so a shell transcript does not right-align under Arabic.
Status
Implemented and green on the fork's master: unit specs, an Arabic Playwright scenario beside the existing settings language-switch test, and the stylesheet gate. Not published to npm, not opened as a pull request here.
Would the maintainers take this upstream? I can split it as core readiness first — the direction field, the root attribute, the theme rule and its spec — so the mechanism lands and is reviewable on its own, with the Arabic pack and the per-package logical-property migration following behind it. Happy to adapt the direction heuristic, the zone list, or the packaging to whatever shape review prefers.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Two threads here already ask for right-to-left rendering:
dir="auto"patch as a ZIP plus a Windows batch installer and asks the maintainers to adoptdir="auto"in the core components.Hello كيف حالك اليومrenders unreadably, traces it to UAX #9 first-strong direction detection, and proposes counting strong characters across the whole string instead.Both are about direction. Neither translates a string, and nothing upstream implements either. I built the other half — an Arabic language pack — and the direction mechanism it needs, and it runs on a fork branch today.
What is implemented
All of it is public on a fork of this repository, pinned here to the commit that merged it:
packages/client/locale-ar, the direction rule inui-theme/src/styles/text-direction.css, the registry contract in the locale README, the gate intext-direction-styles.client.spec.ts, and the browser scenario inarabic-language-pack.e2e.ts.@deepseek-ai/dsh-client-locale-ar: one in-tree client plugin, 34 dictionary files, about 1060 keys, one file per namespace. Each dictionary is declaredsatisfies Record<XxxKey, string>against the key union imported type-only from the owning package, so a key added tozhwithout an Arabic counterpart fails the pack's typecheck rather than showing a missing string at runtime. The plugin registersaddLanguage({ id: 'ar', label: 'العربية', fallback: 'en', direction: 'rtl' })and each namespace as owned effects; an unresolved key falls to English, never to Chinese. It mounts in theweb-appbundle roster, so Arabic is selectable in Settings without an install step.The direction decision, and why it is not
html[dir]The frame does not move.
direction: rtlon the document reorders flex and grid children, which relocates the settings navigation, the row controls, and every icon that sits beside its label — a bilingual reader would meet a different application in each language, and every chrome screenshot would change.Instead the locale plugin publishes the active language's reading order as
data-dsh-text-directionon the root and never writeshtml[dir].ui-themeowns a single rule: elements a component marksdata-dsh-text-zonetaketext-align: rightwhile Arabic is active. 18 zone markers cover the transcript, composer, settings panels, sidebar lists, and the modal, toast, tooltip, and menu bodies. Two things opt back out:dir="ltr"— code blocks, terminal output, diffs, JSON trees, read blocks — where column order carries meaning.data-dsh-text-auto, which takesdir="auto"withunicode-bidi: plaintext, so an Arabic reply lands on the right and an English one on the left inside the same transcript.Component stylesheets that render inside a zone migrated from physical inline-axis properties to logical ones, and a stylesheet spec built on the existing scanner rejects a physical declaration added back to a zone package. Logical properties render identically left-to-right, so the existing
en-USgoldens are the regression proof.Where this meets #696
The
dir="auto"plusunicode-bidi: plaintextabove resolves each paragraph from its first strong character — exactly the rule #696 reports as unreadable when a sentence opens with an English word. The alternative, counting strong characters across the whole string, decides per paragraph but can flip a paragraph's direction while it is being typed. I chose the standard rule and recorded the tension rather than hiding it; if maintainers prefer the dominant-direction detector, it swaps in behind the samedata-dsh-text-automarker without touching the pack or the zone rule.Where this meets #4009
Same intent, different delivery. #4009 applies
dir="auto"broadly through a patch file users re-apply after every update. Here the same attribute is authored in the components, alignment is a theme-owned rule rather than a per-element attribute, and code and terminal output are explicitly excluded, so a shell transcript does not right-align under Arabic.Status
Implemented and green on the fork's
master: unit specs, an Arabic Playwright scenario beside the existing settings language-switch test, and the stylesheet gate. Not published to npm, not opened as a pull request here.Would the maintainers take this upstream? I can split it as core readiness first — the
directionfield, the root attribute, the theme rule and its spec — so the mechanism lands and is reviewable on its own, with the Arabic pack and the per-package logical-property migration following behind it. Happy to adapt the direction heuristic, the zone list, or the packaging to whatever shape review prefers.All reactions