Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Arabic and rtl lang support #2084

Merged
merged 17 commits into from
May 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
340 changes: 340 additions & 0 deletions public/locales/ar/translation.json

Large diffs are not rendered by default.

49 changes: 39 additions & 10 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"deleteRowWarning": "This row will be permanently deleted!",
"addNote": "Add a note",
"domain": "Domain",
"domainTitle": "Domain: {{ val1 }} ({{ val2 }})",
"gloss": "Gloss",
"glosses": "Glosses",
"pressEnter": "Press enter to save word",
Expand Down Expand Up @@ -225,11 +226,8 @@
"noHistory": "Nothing yet",
"done": "All done"
},
"progress": {
"step": "Step",
"stepMerge": "Merge Set",
"of": "of"
}
"progress": "Step {{ val1 }} of {{ val2 }}",
"progressMerge": "Merge Set {{ val1 }} of {{ val2 }}"
},
"createStrWordInv": {
"title": "Create Structural Word Inventory"
Expand Down Expand Up @@ -261,13 +259,43 @@
"domain": "Domains cannot be left blank",
"senses": "Cannot save an entry with no senses",
"vernacular": "Vernacular cannot be left blank"
},
"columns": {
"definitions": "Definitions",
"delete": "Delete",
"domains": "Domains",
"flag": "Flag",
"glosses": "Glosses",
"note": "Note",
"pronunciations": "Pronunciations",
"senses": "Senses",
"vernacular": "Vernacular"
},
"materialTable": {
"body": {
"edit": "Edit",
"emptyDataSourceMessage": "No entries to display",
"filter": "Filter"
},
"pagination": {
"labelDisplayedRows": "{from}-{to} of {count}",
"labelRows": "rows",
"labelRowsPerPage": "Rows per page:",
"first": "First Page",
"last": "Last Page",
"next": "Next Page",
"previous": "Previous Page"
},
"toolbar": {
"search": "Search"
}
}
},
"charInventory": {
"title": "Create Character Inventory",
"characters": "characters",
"examples": "Examples",
"occurrences": "occurrences",
"occurrences": "{{ val }} occurrences",
"status": "status",
"sortBy": "Sort by",
"characterSet": {
Expand Down Expand Up @@ -382,7 +410,7 @@
"deleteRecording": "Delete Recording"
},
"statistics": {
"dataStatistics": "Data Statistics: ",
"title": "Data Statistics: {{ val }}",
"domainNumber": "Domain Number:",
"domainName": "Domain Name:",
"countSenses": "Words:",
Expand All @@ -394,9 +422,10 @@
"dayView": "Words per Day",
"estimate": "Workshop Estimate",
"domainProgress": "Domain Progress",
"domainsCollected": "Domains Collected:",
"wordsCollected": "Words Collected:",
"domainsCollected": "Domains Collected: {{ val }}",
"wordsCollected": "Words Collected: {{ val }}",
"wordsPerDay": "Words Collected Per User Per Day",
"workshopSchedule": "Workshop Schedule"
"workshopSchedule": "Workshop Schedule",
"percent": "{{ val }}%"
}
}
46 changes: 22 additions & 24 deletions src/components/App/component.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import loadable from "@loadable/component";
import React, { ReactElement, Suspense } from "react";
import { ReactElement, Suspense } from "react";
import { Route, Switch } from "react-router-dom";

import { Path } from "browserHistory";
Expand All @@ -18,27 +18,25 @@ const AppWithBar = loadable(() => import("components/App/AppLoggedIn"));
/**
* The top-level component
*/
export default class App extends React.Component {
render(): ReactElement {
return (
<div className="App">
<Suspense fallback={<div />}>
<AnnouncementBanner />
<Switch>
<Route exact path={Path.Root} component={LandingPage} />
<PrivateRoute path={Path.ProjScreen} component={AppWithBar} />
<Route path={Path.Login} component={Login} />
<Route path={Path.SignUp} component={SignUp} />
<Route path={`${Path.PwReset}/:token`} component={PasswordReset} />
<Route path={Path.PwRequest} component={ResetRequest} />
<Route
path={`${Path.ProjInvite}/:project/:token`}
component={ProjectInvite}
/>
<Route component={PageNotFound} />
</Switch>
</Suspense>
</div>
);
}
export default function App(): ReactElement {
return (
<div className="App">
<Suspense fallback={<div />}>
<AnnouncementBanner />
<Switch>
<Route exact path={Path.Root} component={LandingPage} />
<PrivateRoute path={Path.ProjScreen} component={AppWithBar} />
<Route path={Path.Login} component={Login} />
<Route path={Path.SignUp} component={SignUp} />
<Route path={`${Path.PwReset}/:token`} component={PasswordReset} />
<Route path={Path.PwRequest} component={ResetRequest} />
<Route
path={`${Path.ProjInvite}/:project/:token`}
component={ProjectInvite}
/>
<Route component={PageNotFound} />
</Switch>
</Suspense>
</div>
);
}
4 changes: 2 additions & 2 deletions src/components/AppBar/AppBarComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ export default function AppBarComponent(): ReactElement {
spacing={2}
alignItems="center"
>
<Grid item xs={7} md={5} lg={4}>
<Grid item xs={8} sm={7} md={6} lg={4}>
<Logo />
{!!getProjectId() && (
<NavigationButtons currentTab={currentTab} />
)}
</Grid>
<Grid item xs={2} sm={3} md={4}>
<Grid item xs={1} sm={2} md={3} lg={4}>
{!!getProjectId() && (
<ProjectNameButton currentTab={currentTab} />
)}
Expand Down
7 changes: 5 additions & 2 deletions src/components/AppBar/Logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ import smallLogo from "resources/CombineSmallLogoV1.png";
export default function Logo(): ReactElement {
return (
<Button onClick={() => history.push(Path.ProjScreen)} id="logo-button">
<Hidden smDown>
<Hidden mdDown>
<img src={logo} height="50" alt="Logo" />
</Hidden>
<Hidden mdUp smDown>
<img src={smallLogo} height="40" alt="Logo" />
</Hidden>
<Hidden smUp>
<img src={smallLogo} height="50" alt="Logo" />
<img src={smallLogo} height="30" alt="Logo" />
</Hidden>
</Button>
);
Expand Down
7 changes: 4 additions & 3 deletions src/components/DataEntry/DataEntryHeader/DataEntryHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ export class DataEntryHeader extends React.Component<DataEntryHeaderProps> {
align="center"
style={{ marginBottom: theme.spacing(2) }}
>
{this.props.t("addWords.domain")}
{": "}
{this.props.domain.name + " (" + this.props.domain.id + ")"}
{this.props.t("addWords.domainTitle", {
val1: this.props.domain.name,
val2: this.props.domain.id,
})}
<Typography>{this.props.domain.description}</Typography>
<Switch
id="questionVisibilitySwitch"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import NewEntry from "components/DataEntry/DataEntryTable/NewEntry/NewEntry";
import { newSemanticDomain } from "types/semanticDomain";
import { newWritingSystem } from "types/writingSystem";

jest.mock("@mui/material/Autocomplete", () => "div");

jest.mock("components/Pronunciations/PronunciationsComponent", () => "div");
jest.mock("components/Pronunciations/Recorder");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ jest.mock("backend", () => ({
jest.mock("backend/localStorage", () => ({
getUserId: () => mockUserId,
}));
jest.mock("components/DataEntry/DataEntryTable/NewEntry/SenseDialog");
jest.mock(
"components/DataEntry/DataEntryTable/NewEntry/VernDialog",
() => "div"
);
jest.mock(
"components/DataEntry/DataEntryTable/RecentEntry/RecentEntry",
() => "div"
Expand Down
9 changes: 3 additions & 6 deletions src/components/Login/LoginPage/tests/LoginComponent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,11 @@ jest.mock("backend", () => ({
}));

const LOGOUT = jest.fn();
var loginMaster: renderer.ReactTestRenderer;
var loginHandle: renderer.ReactTestInstance;
let loginMaster: renderer.ReactTestRenderer;
let loginHandle: renderer.ReactTestInstance;

const DATA = "stuff";
const MOCK_EVENT = {
preventDefault: jest.fn(),
target: { value: DATA },
};
const MOCK_EVENT = { preventDefault: jest.fn(), target: { value: DATA } };

describe("Testing login component", () => {
beforeEach(() => {
Expand Down
11 changes: 3 additions & 8 deletions src/components/Login/SignUpPage/tests/SignUpComponent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,11 @@ jest.mock("backend", () => ({
}));

const mockReset = jest.fn();
var signUpMaster: renderer.ReactTestRenderer;
var signUpHandle: renderer.ReactTestInstance;
let signUpMaster: renderer.ReactTestRenderer;
let signUpHandle: renderer.ReactTestInstance;

const DATA = "stuff";
const MOCK_EVENT = {
preventDefault: jest.fn(),
target: {
value: DATA,
},
};
const MOCK_EVENT = { preventDefault: jest.fn(), target: { value: DATA } };

describe("Testing sign up component", () => {
beforeEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { ProjectSwitch } from "components/ProjectSettings/ProjectSwitch/ProjectS
import { newProject, randomProject } from "types/project";

const projects = [randomProject(), randomProject(), randomProject()];
var switchMaster: renderer.ReactTestRenderer;
var switchHandle: ProjectSwitch;
let switchMaster: renderer.ReactTestRenderer;
let switchHandle: ProjectSwitch;

const createMockStore = configureMockStore();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import theme from "types/theme";
jest.mock("components/Pronunciations/Recorder");

// Variables
var testRenderer: renderer.ReactTestRenderer;
let testRenderer: renderer.ReactTestRenderer;

const createMockStore = configureMockStore();
const mockStore = createMockStore({ pronunciationsState });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const mockProjects = [randomProject(), randomProject(), randomProject()];

jest.mock("components/ProjectExport/ExportButton", () => "div");

var testRenderer: renderer.ReactTestRenderer;
let testRenderer: renderer.ReactTestRenderer;

beforeAll(() => {
renderer.act(() => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/Statistics/Chart/LineChartComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@ export default function LineChartComponent(props: LineChartProps) {
useEffect(() => {
const updateChartList = async () => {
const tempDate = await props.fetchData();
var updateEstimateDate: LineChartDataProps = {
const updateEstimateDate: LineChartDataProps = {
labels: [],
datasets: [],
};
if (tempDate !== undefined) {
// Get array of unique Color
var palette: chroma.Color[];
let palette: chroma.Color[];
if (tempDate.datasets.length) {
palette = distinctColors({ count: tempDate.datasets.length });
}
Expand Down
10 changes: 6 additions & 4 deletions src/components/Statistics/ProgressBar/LinearProgressBar.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import Box from "@mui/material/Box";
import LinearProgress from "@mui/material/LinearProgress";
import Typography from "@mui/material/Typography";
import { useTranslation } from "react-i18next";

interface ProgressBarProps {
value: number;
}

export default function LinearProgressWithLabel(props: ProgressBarProps) {
const { t } = useTranslation();
return (
<Box sx={{ display: "flex", alignItems: "center", width: "50%" }}>
<Box sx={{ width: "100%", mr: 1 }}>
<Box sx={{ width: "100%", m: 1 }}>
<LinearProgress variant="determinate" {...props} />
</Box>
<Box>
<Typography variant="body2" color="text.secondary">{`${Math.round(
props.value
)}%`}</Typography>
<Typography variant="body2" color="text.secondary">
{t("statistics.percent", { val: Math.round(props.value) })}
</Typography>
</Box>
</Box>
);
Expand Down
45 changes: 19 additions & 26 deletions src/components/Statistics/ProgressBar/ProgressBarComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import {
Divider,
List,
ListItem,
ListItemText,
Theme,
Typography,
} from "@mui/material";
import { Divider, List, ListItem, ListItemText, Theme } from "@mui/material";
import { makeStyles } from "@mui/styles";
import { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
Expand All @@ -32,25 +25,23 @@ export default function ProgressBarComponent() {

useEffect(() => {
const updateProgress = async () => {
const statisticsList = await getSemanticDomainCounts(
const statList = await getSemanticDomainCounts(
LocalStorage.getProjectId(),
defaultWritingSystem.bcp47
);
var domainCount = 0;
var wordCount = 0;
statisticsList?.forEach((element) => {
if (element.count > 0) {
domainCount++;
wordCount += element.count;
}
});
let domainCount = 0;
let wordCount = 0;
if (statList?.length) {
statList.forEach((s) => {
if (s.count) {
domainCount++;
wordCount += s.count;
}
});
setProgressRatio(Math.ceil((domainCount * 100) / statList.length));
}
setTotalDomainCount(domainCount);
setTotalWordCount(wordCount);
statisticsList
? setProgressRatio(
Math.ceil((domainCount * 100) / statisticsList!.length)
)
: null;
};

updateProgress();
Expand All @@ -64,13 +55,15 @@ export default function ProgressBarComponent() {
</ListItem>
<Divider />
<ListItem>
<ListItemText primary={t("statistics.domainsCollected")} />
<Typography>{totalDomainCount}</Typography>
<ListItemText
primary={t("statistics.domainsCollected", { val: totalDomainCount })}
/>
</ListItem>
<Divider />
<ListItem>
<ListItemText primary={t("statistics.wordsCollected")} />
<Typography>{totalWordCount}</Typography>
<ListItemText
primary={t("statistics.wordsCollected", { val: totalWordCount })}
/>
</ListItem>
</List>
);
Expand Down
Loading