协作头脑风暴
brainstorming
在实现前澄清需求、探索设计选择,并形成清晰的开发方向。
rtl-internationalization【开发与工程】Right-to-left (RTL) layout and bidirectional text support for Hebrew, Arabic, Persian, and Urdu interfaces. Use when building UI that must support RTL languages, converting physical CSS/Tailwind properties to logical ones, handling mixed-direction (bidi) text, mirroring directional icons, or testing an app with dir="rtl".
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Supporting RTL languages such as Hebrew, Arabic, Persian, and Urdu requires building layouts with direction-agnostic CSS and treating text direction as a first-class, runtime-switchable property rather than a fixed assumption baked into left/right styles.
margin-left/right, padding-left/right, left/right positioning, text-align: left/right, and Tailwind classes like ml-*, mr-*, pl-*, pr-*, left-*, right-*.margin-inline-start, ms-*, etc.) so the browser flips it automatically based on dir.dir="rtl" (or dir="auto") on <html> or a top-level container, driven by the active locale, not hardcoded per component.<bdi>.Intl APIs for numbers, currency, and dates instead of manual formatting.dir="rtl" and real RTL content (not just mirrored LTR placeholder text) and visually verify every screen.Always use CSS logical properties instead of physical ones — logical properties resolve to the correct physical side automatically based on the element's direction and writing-mode, so the same stylesheet works for LTR and RTL without duplication.
| Physical (avoid) | Logical (use) |
|---|---|
margin-left | margin-inline-start |
margin-right | margin-inline-end |
padding-left | padding-inline-start |
padding-right | padding-inline-end |
left | inset-inline-start |
right | inset-inline-end |
border-left | border-inline-start |
border-right | border-inline-end |
text-align: left | text-align: start |
text-align: right | text-align: end |
/* Before: breaks in RTL */
.card {
margin-left: 1rem;
padding-right: 1.5rem;
border-left: 2px solid var(--border);
text-align: left;
}
/* After: direction-agnostic */
.card {
margin-inline-start: 1rem;
padding-inline-end: 1.5rem;
border-inline-start: 2px solid var(--border);
text-align: start;
}
Use Tailwind's logical utilities instead of the directional (l/r) ones:
ms-4 instead of ml-4 (margin-inline-start)me-4 instead of mr-4 (margin-inline-end)ps-4 instead of pl-4 (padding-inline-start)pe-4 instead of pr-4 (padding-inline-end)start-0 instead of left-0 (inset-inline-start)end-0 instead of right-0 (inset-inline-end)text-start instead of text-lefttext-end instead of text-right<!-- Before -->
<div class="ml-4 pr-6 text-left">...</div>
<!-- After -->
<div class="ms-4 pe-6 text-start">...</div>
React Native's Yoga layout engine also supports logical properties — use them instead of Left/Right variants:
paddingStart / paddingEnd instead of paddingLeft / paddingRightmarginStart / marginEnd instead of marginLeft / marginRightborderStartWidth / borderEndWidth instead of borderLeftWidth / borderRightWidthstart / end instead of left / right in absolute positioningconst styles = StyleSheet.create({
row: {
flexDirection: 'row',
paddingStart: 16,
paddingEnd: 16,
},
badge: {
position: 'absolute',
end: 8, // flips automatically with I18nManager.isRTL
top: 8,
},
})
Wrap text whose direction may differ from its surrounding context — usernames, product codes, file paths, or any user-generated content interpolated into a translated sentence — with <bdi> so the browser's bidi algorithm isolates it correctly.
<p>User <bdi>{userName}</bdi> posted a comment</p>
<p>Order number: <bdi>{orderCode}</bdi> has shipped</p>
Without <bdi>, a Latin-script username embedded in an Arabic sentence (or vice versa) can visually reorder surrounding punctuation and neighboring words.
/* Mirror an icon only when the document is RTL */
[dir="rtl"] .icon-chevron-forward {
transform: scaleX(-1);
}
// React: pick the mirrored icon variant based on direction
function BackButton({ dir }: { dir: 'ltr' | 'rtl' }) {
const Icon = dir === 'rtl' ? ChevronRightIcon : ChevronLeftIcon
return (
<button aria-label="Back">
<Icon aria-hidden="true" />
</button>
)
}
t(), intl.formatMessage(), etc.) so it can be localized and so RTL locales get correct punctuation and word order.Intl.NumberFormat for numbers and currency instead of manual string formatting — digit shaping and grouping separators differ by locale.Intl.DateTimeFormat for dates and times instead of manual concatenation.dir="auto" on user-generated content fields (comments, chat messages) so the browser infers direction from content, and set an explicit dir="rtl" or dir="ltr" on the document root based on the active locale.const currency = new Intl.NumberFormat('ar-EG', {
style: 'currency',
currency: 'EGP',
}).format(1234.5)
// "١٬٢٣٤٫٥٠ ج.م."
document.documentElement.dir = locale.startsWith('ar') || locale.startsWith('he') ? 'rtl' : 'ltr'
document.documentElement.lang = locale
dir="rtl" applied to the root element, not just a mirrored screenshot of the LTR layout.dir — many popular libraries default to LTR-only and need an explicit RTL mode or CSS override.ml-*, left, text-align: left) that silently break when a locale switches to RTL.name + ": " + value) instead of using ICU message formatting, which breaks word order in RTL locales.dir="rtl" alone fixes everything — inline styles, canvas-drawn UI, and absolutely-positioned elements using left/right still need manual conversion to logical properties.