Skip to content

Commit 5ec54e2

Browse files
Display UI in RTL languages correctly
1 parent a62a6ba commit 5ec54e2

File tree

7 files changed

+60
-14
lines changed

7 files changed

+60
-14
lines changed

src/components/EditorCanvas/Table.jsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import { useLayout, useSettings, useDiagram, useSelect } from "../../hooks";
1818
import TableInfo from "../EditorSidePanel/TablesTab/TableInfo";
1919
import { useTranslation } from "react-i18next";
2020
import { dbToTypes } from "../../data/datatypes";
21+
import { isRtl } from "../../i18n/utils/rtl";
22+
import i18n from "../../i18n/i18n";
2123

2224
export default function Table(props) {
2325
const [hoveredField, setHoveredField] = useState(-1);
@@ -84,6 +86,7 @@ export default function Table(props) {
8486
? "border-solid border-blue-500"
8587
: "border-zinc-500"
8688
}`}
89+
style={{ direction: "ltr" }}
8790
>
8891
<div
8992
className="h-[10px] w-full rounded-t-md"
@@ -190,7 +193,10 @@ export default function Table(props) {
190193
key={i}
191194
content={
192195
<div className="popover-theme">
193-
<div className="flex justify-between items-center pb-2">
196+
<div
197+
className="flex justify-between items-center pb-2"
198+
style={{ direction: "ltr" }}
199+
>
194200
<p className="me-4 font-bold">{e.name}</p>
195201
<p className="ms-4">
196202
{e.type +
@@ -235,6 +241,11 @@ export default function Table(props) {
235241
}
236242
position="right"
237243
showArrow
244+
style={
245+
isRtl(i18n.language)
246+
? { direction: "rtl" }
247+
: { direction: "ltr" }
248+
}
238249
>
239250
{field(e, i)}
240251
</Popover>

src/components/EditorHeader/ControlPanel.jsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useState } from "react";
22
import {
33
IconCaretdown,
44
IconChevronRight,
5+
IconChevronLeft,
56
IconChevronUp,
67
IconChevronDown,
78
IconSaveStroked,
@@ -68,6 +69,7 @@ import { useTranslation } from "react-i18next";
6869
import { exportSQL } from "../../utils/exportSQL";
6970
import { databases } from "../../data/databases";
7071
import { jsonToMermaid } from "../../utils/exportAs/mermaid";
72+
import { isRtl } from "../../i18n/utils/rtl";
7173

7274
export default function ControlPanel({
7375
diagramId,
@@ -109,7 +111,7 @@ export default function ControlPanel({
109111
const { undoStack, redoStack, setUndoStack, setRedoStack } = useUndoRedo();
110112
const { selectedElement, setSelectedElement } = useSelect();
111113
const { transform, setTransform } = useTransform();
112-
const { t } = useTranslation();
114+
const { t, i18n } = useTranslation();
113115
const navigate = useNavigate();
114116

115117
const invertLayout = (component) =>
@@ -1374,15 +1376,20 @@ export default function ControlPanel({
13741376

13751377
function toolbar() {
13761378
return (
1377-
<div className="py-1.5 px-5 flex justify-between items-center rounded-xl my-1 sm:mx-1 xl:mx-6 select-none overflow-hidden toolbar-theme">
1379+
<div
1380+
className="py-1.5 px-5 flex justify-between items-center rounded-xl my-1 sm:mx-1 xl:mx-6 select-none overflow-hidden toolbar-theme"
1381+
style={isRtl(i18n.language) ? { direction: "rtl" } : {}}
1382+
>
13781383
<div className="flex justify-start items-center">
13791384
<LayoutDropdown />
13801385
<Divider layout="vertical" margin="8px" />
13811386
<Dropdown
13821387
style={{ width: "240px" }}
13831388
position="bottomLeft"
13841389
render={
1385-
<Dropdown.Menu>
1390+
<Dropdown.Menu
1391+
style={isRtl(i18n.language) ? { direction: "rtl" } : {}}
1392+
>
13861393
<Dropdown.Item
13871394
onClick={fitWindow}
13881395
style={{ display: "flex", justifyContent: "space-between" }}
@@ -1562,7 +1569,10 @@ export default function ControlPanel({
15621569

15631570
function header() {
15641571
return (
1565-
<nav className="flex justify-between pt-1 items-center whitespace-nowrap">
1572+
<nav
1573+
className="flex justify-between pt-1 items-center whitespace-nowrap"
1574+
style={isRtl(i18n.language) ? { direction: "rtl" } : {}}
1575+
>
15661576
<div className="flex justify-start items-center">
15671577
<Link to="/">
15681578
<img
@@ -1608,7 +1618,10 @@ export default function ControlPanel({
16081618
<Dropdown
16091619
key={category}
16101620
position="bottomLeft"
1611-
style={{ width: "240px" }}
1621+
style={{
1622+
width: "240px",
1623+
direction: isRtl(i18n.language) ? "rtl" : "ltr",
1624+
}}
16121625
render={
16131626
<Dropdown.Menu>
16141627
{Object.keys(menu[category]).map((item, index) => {
@@ -1642,7 +1655,12 @@ export default function ControlPanel({
16421655
onClick={menu[category][item].function}
16431656
>
16441657
{t(item)}
1645-
<IconChevronRight />
1658+
1659+
{isRtl(i18n.language) ? (
1660+
<IconChevronLeft />
1661+
) : (
1662+
<IconChevronRight />
1663+
)}
16461664
</Dropdown.Item>
16471665
</Dropdown>
16481666
);

src/components/EditorHeader/LayoutDropdown.jsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { Dropdown } from "@douyinfe/semi-ui";
77
import { useFullscreen, useLayout } from "../../hooks";
88
import { enterFullscreen, exitFullscreen } from "../../utils/fullscreen";
99
import { useTranslation } from "react-i18next";
10+
import { isRtl } from "../../i18n/utils/rtl";
11+
import i18n from "../../i18n/i18n";
1012

1113
export default function LayoutDropdown() {
1214
const fullscreen = useFullscreen();
@@ -19,7 +21,10 @@ export default function LayoutDropdown() {
1921
return (
2022
<Dropdown
2123
position="bottomLeft"
22-
style={{ width: "180px" }}
24+
style={{
25+
width: "180px",
26+
direction: isRtl(i18n.language) ? "rtl" : "ltr",
27+
}}
2328
render={
2429
<Dropdown.Menu>
2530
<Dropdown.Item
@@ -48,9 +53,7 @@ export default function LayoutDropdown() {
4853
</Dropdown.Item>
4954
<Dropdown.Divider />
5055
<Dropdown.Item
51-
icon={
52-
fullscreen ? <IconCheckboxTick /> : <div className="px-2" />
53-
}
56+
icon={fullscreen ? <IconCheckboxTick /> : <div className="px-2" />}
5457
onClick={() => {
5558
if (fullscreen) {
5659
exitFullscreen();

src/components/EditorHeader/Modal/Modal.jsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import { githubLight } from "@uiw/codemirror-theme-github";
3737
import { useTranslation } from "react-i18next";
3838
import { importSQL } from "../../../utils/importSQL";
3939
import { databases } from "../../../data/databases";
40+
import { isRtl } from "../../../i18n/utils/rtl";
4041

4142
const languageExtension = {
4243
sql: [sql()],
@@ -53,7 +54,7 @@ export default function Modal({
5354
setExportData,
5455
importDb,
5556
}) {
56-
const { t } = useTranslation();
57+
const { t, i18n } = useTranslation();
5758
const { setTables, setRelationships, database, setDatabase } = useDiagram();
5859
const { setNotes } = useNotes();
5960
const { setAreas } = useAreas();
@@ -324,6 +325,7 @@ export default function Modal({
324325

325326
return (
326327
<SemiUIModal
328+
style={isRtl(i18n.language) ? { direction: "rtl" } : {}}
327329
title={getModalTitle(modal)}
328330
visible={modal !== MODAL.NONE}
329331
onOk={getModalOnOk}
@@ -362,7 +364,11 @@ export default function Modal({
362364
}}
363365
cancelText={t("cancel")}
364366
width={modal === MODAL.NEW || modal === MODAL.OPEN ? 740 : 600}
365-
bodyStyle={{ maxHeight: window.innerHeight - 280, overflow: "auto" }}
367+
bodyStyle={{
368+
maxHeight: window.innerHeight - 280,
369+
overflow: "auto",
370+
direction: "ltr",
371+
}}
366372
>
367373
{getModalBody()}
368374
</SemiUIModal>

src/components/EditorSidePanel/SidePanel.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import { useTranslation } from "react-i18next";
1111
import { useMemo } from "react";
1212
import { databases } from "../../data/databases";
1313
import EnumsTab from "./EnumsTab/EnumsTab";
14+
import { isRtl } from "../../i18n/utils/rtl";
15+
import i18n from "../../i18n/i18n";
1416

1517
export default function SidePanel({ width, resize, setResize }) {
1618
const { layout } = useLayout();
@@ -46,7 +48,7 @@ export default function SidePanel({ width, resize, setResize }) {
4648
});
4749
}
4850

49-
return tabs;
51+
return isRtl(i18n.language) ? tabs.reverse() : tabs;
5052
}, [t, database]);
5153

5254
return (
@@ -64,6 +66,7 @@ export default function SidePanel({ width, resize, setResize }) {
6466
setSelectedElement((prev) => ({ ...prev, currentTab: key }))
6567
}
6668
collapsible
69+
tabBarStyle={{ direction: "ltr" }}
6770
>
6871
{tabList.length &&
6972
tabList.map((tab) => (

src/components/Workspace.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import FloatingControls from "./FloatingControls";
2222
import { Modal } from "@douyinfe/semi-ui";
2323
import { useTranslation } from "react-i18next";
2424
import { databases } from "../data/databases";
25+
import { isRtl } from "../i18n/utils/rtl";
26+
import i18n from "../i18n/i18n";
2527

2628
export default function WorkSpace() {
2729
const [id, setId] = useState(0);
@@ -358,6 +360,7 @@ export default function WorkSpace() {
358360
// https://stackoverflow.com/a/70976017/1137077
359361
e.target.releasePointerCapture(e.pointerId);
360362
}}
363+
style={isRtl(i18n.language) ? { direction: "rtl" } : {}}
361364
>
362365
{layout.sidebar && (
363366
<SidePanel resize={resize} setResize={setResize} width={width} />

src/i18n/utils/rtl.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const rtlLanguages = ["ar", "he", "fa", "ps", "ur"];
2+
export const isRtl = (language) => rtlLanguages.includes(language);

0 commit comments

Comments
 (0)