Skip to content

Commit c61a793

Browse files
committed
feat: add internationalization support for explainers
- Integrated i18next for translation in Explainer components. - Updated ExplainerParametersTab, ExplainersDashboard, ExplainersGrid, ExplainersPlot, ExplainersCard, NewGlobalExplainerModal, NewLocalExplainerModal, SelectDatasetStep, SetNameAndExplainerStep, SplitSelector, and TrainedModelsTable to use translated strings. - Created English and Spanish translation files for common and explainer-specific labels, messages, and errors. - Enhanced user experience by providing localized text for buttons, labels, and error messages.
1 parent ce26ff0 commit c61a793

20 files changed

Lines changed: 409 additions & 150 deletions

DashAI/front/src/components/explainers/ConfigureExplainerStep.jsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import PropTypes from "prop-types";
1111
import FormSchema from "../shared/FormSchema";
1212
import FormSchemaLayout from "../shared/FormSchemaLayout";
1313
import useSchema from "../../hooks/useSchema";
14+
import { useTranslation } from "react-i18next";
1415

1516
function ConfigureExplainerStep({
1617
newExpl,
@@ -21,6 +22,7 @@ function ConfigureExplainerStep({
2122
}) {
2223
const { defaultValues } = useSchema({ modelName: newExpl.explainer_name });
2324
const [error, setError] = useState(false);
25+
const { t } = useTranslation(["explainers"]);
2426

2527
const isParamsEmpty =
2628
!newExpl.parameters || Object.keys(newExpl.parameters).length === 0;
@@ -83,7 +85,7 @@ function ConfigureExplainerStep({
8385
>
8486
<Grid size={{ xs: 12 }}>
8587
<Typography variant="h5" component="h3">
86-
Configure your Explainer
88+
{t("explainers:label.configureExplainer")}
8789
</Typography>
8890
</Grid>
8991
{/* Configure dataloader parameters */}
@@ -93,7 +95,9 @@ function ConfigureExplainerStep({
9395
sx={{ p: 4, maxHeight: "55vh", overflow: "auto" }}
9496
>
9597
<Stack spacing={3}>
96-
<DialogContentText>Explainer configuration</DialogContentText>
98+
<DialogContentText>
99+
{t("explainers:label.explainerConfiguration")}
100+
</DialogContentText>
97101

98102
<FormSchemaLayout>
99103
<FormSchema

DashAI/front/src/components/explainers/ExplainerConfiguration.jsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ import { DialogContentText, Grid, Paper } from "@mui/material";
33
import PropTypes from "prop-types";
44

55
import ParameterForm from "../configurableObject/ParameterForm";
6+
import { useTranslation } from "react-i18next";
67

78
function ExplainerConfiguration({ paramsSchema, updateParameters }) {
9+
const { t } = useTranslation(["explainers"]);
10+
811
return (
912
<Paper
1013
variant="outlined"
@@ -13,7 +16,9 @@ function ExplainerConfiguration({ paramsSchema, updateParameters }) {
1316
<Grid container direction={"column"} alignItems={"center"}>
1417
{/* Form title */}
1518
<Grid>
16-
<DialogContentText>Explainer configuration</DialogContentText>
19+
<DialogContentText>
20+
{t("explainers:label.explainerConfiguration")}
21+
</DialogContentText>
1722
</Grid>
1823
<Grid sx={{ p: 3 }}>
1924
{/* Main dataloader form */}

DashAI/front/src/components/explainers/ExplainerData.jsx

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
import { useSnackbar } from "notistack";
2-
import React, { useEffect, useState } from "react";
2+
import React, { useEffect, useMemo, useState } from "react";
33
import { Tabs, Tab, Paper, Box, Button } from "@mui/material";
44
import { useNavigate, useParams } from "react-router-dom";
55
import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew";
66
import CustomLayout from "../custom/CustomLayout";
77
import { getExplainers } from "../../api/explainer";
88
import ExplainerInfoTab from "./ExplainerInfoTab";
99
import ExplainerParametersTab from "./ExplainerParametersTab";
10+
import { useTranslation } from "react-i18next";
1011

11-
const tabs = [
12-
{ label: "Explainer parameters", value: 0, disabled: false },
13-
{ label: "Info", value: 1, disabled: false },
14-
];
1512
/**
1613
* Component that renders multiple tabs to visualize the results of a specific explainer.
1714
*/
@@ -23,6 +20,19 @@ function ExplainerData() {
2320
const [explainerData, setExplainerData] = useState({});
2421
const [updateDataFlag, setUpdateDataFlag] = useState(false);
2522
const [currentTab, setCurrentTab] = useState(0);
23+
const { t } = useTranslation(["explainers"]);
24+
25+
const tabs = useMemo(
26+
() => [
27+
{
28+
label: t("explainers:label.explainerParameters"),
29+
value: 0,
30+
disabled: false,
31+
},
32+
{ label: t("common:info"), value: 1, disabled: false },
33+
],
34+
[t],
35+
);
2636

2737
const handleTabChange = (event, newValue) => {
2838
setCurrentTab(newValue);
@@ -40,7 +50,8 @@ function ExplainerData() {
4050
}
4151
} catch (error) {
4252
enqueueSnackbar(
43-
`Error while trying to obtain data of the explainer with id: ${id}`,
53+
t("explainers:error.fetchDataError", { explainerId: id }),
54+
{ variant: "error" },
4455
);
4556
if (error.response) {
4657
console.error("Response error:", error.message);
@@ -73,7 +84,7 @@ function ExplainerData() {
7384
navigate(`/app/explainers/runs/${explainerData.run_id}`);
7485
}}
7586
>
76-
Return to table
87+
{t("explainers:button.backToExplainers")}
7788
</Button>
7889

7990
{/* Tabs */}

DashAI/front/src/components/explainers/ExplainerInfoTab.jsx

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,29 @@
11
import { Divider, Grid, Typography } from "@mui/material";
22
import React from "react";
33
import PropTypes from "prop-types";
4+
import { useTranslation } from "react-i18next";
5+
import { formatDate } from "../../utils";
46

5-
const explainerInfo = [
6-
{ key: "id", label: "Explainer ID" },
7-
{ key: "name", label: "Name" },
8-
{ key: "run_id", label: "Run ID" },
9-
{ key: "explainer_name", label: "Explainer Name" },
10-
{ key: "dataset_id", label: "Dataset ID" },
11-
{ key: "explanation_path", label: "Explanation Path" },
12-
{ key: "plot_path", label: "Plot Path" },
13-
{ key: "status", label: "Status" },
14-
];
15-
16-
const explainerDateInfo = [{ key: "created", label: "Created" }];
17-
18-
const formatDate = (dateStr) => {
19-
const date = new Date(dateStr);
20-
const options = {
21-
year: "numeric",
22-
month: "long",
23-
day: "numeric",
24-
hour: "numeric",
25-
minute: "2-digit",
26-
second: "2-digit",
27-
locale: "en-US",
28-
};
29-
30-
return date.toLocaleString("en-US", options);
31-
};
327
/**
338
* Component that displays general information associated with a explainer.
349
* @param {object} explainerData object that contains all the necesary info of the explainer
3510
*/
3611
function ExplainerInfoTab({ explainerData }) {
12+
const { t } = useTranslation(["explainers", "common"]);
13+
14+
const explainerInfo = [
15+
{ key: "id", label: t("common:id") },
16+
{ key: "name", label: t("common:name") },
17+
{ key: "run_id", label: t("explainers:label.runId") },
18+
{ key: "explainer_name", label: t("explainers:label.explainerName") },
19+
{ key: "dataset_id", label: t("explainers:label.datasetId") },
20+
{ key: "explanation_path", label: t("explainers:label.explanationPath") },
21+
{ key: "plot_path", label: t("explainers:label.plotPath") },
22+
{ key: "status", label: t("common:status") },
23+
];
24+
25+
const explainerDateInfo = [{ key: "created", label: t("common:created") }];
26+
3727
return (
3828
<Grid container direction="column">
3929
{/* Explainer name related info */}

DashAI/front/src/components/explainers/ExplainerParametersTab.jsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ import {
77
Typography,
88
} from "@mui/material";
99
import ParameterListItem from "./ParameterListItem";
10+
import { useTranslation } from "react-i18next";
1011

1112
/**
1213
* Component that displays the parameters associated with a explainer.
1314
* @param {object} explainerData object that contains all the necesary info of the explainer
1415
*/
1516
function ExplainerParametersTab({ explainerData }) {
1617
const [displayMode, setDisplayMode] = useState("nested-list");
18+
const { t } = useTranslation(["common"]);
1719
return (
1820
<Grid container direction="column">
1921
{/* Toggle to select the mode of displaying the JSON object. */}
@@ -28,16 +30,16 @@ function ExplainerParametersTab({ explainerData }) {
2830
}}
2931
sx={{ float: "right" }}
3032
>
31-
<ToggleButton value="nested-list">List</ToggleButton>
32-
<ToggleButton value="json">JSON</ToggleButton>
33+
<ToggleButton value="nested-list">{t("common:list")}</ToggleButton>
34+
<ToggleButton value="json">{t("common:json")}</ToggleButton>
3335
</ToggleButtonGroup>
3436
</Grid>
3537

3638
{/* JSON object display */}
3739
<Grid>
3840
{displayMode === "nested-list" && (
3941
<ParameterListItem
40-
name="Parameters"
42+
name={t("common:parameters")}
4143
value={explainerData.parameters}
4244
/>
4345
)}

DashAI/front/src/components/explainers/ExplainersDashboard.jsx

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,7 @@ import NewLocalExplainerModal from "./NewLocalExplainerModal";
1010
import ExplainersGrid from "./ExplainersGrid";
1111
import TimestampWrapper from "../shared/TimestampWrapper";
1212
import { TIMESTAMP_KEYS } from "../../constants/timestamp";
13-
14-
const tabs = [
15-
{ label: "Global Explanations", value: 0, disabled: false },
16-
{ label: "Local Explanations", value: 1, disabled: false },
17-
];
13+
import { useTranslation } from "react-i18next";
1814

1915
export default function ExplainersDashboard() {
2016
const { id } = useParams();
@@ -26,6 +22,7 @@ export default function ExplainersDashboard() {
2622
useState(false);
2723
const [showNewLocalExplainerModal, setShowNewLocalExplainerModal] =
2824
useState(false);
25+
const { t } = useTranslation(["explainers"]);
2926

3027
const handleNewGlobalExplainerModal = () => {
3128
setShowNewGlobalExplainerModal(true);
@@ -37,6 +34,19 @@ export default function ExplainersDashboard() {
3734

3835
const [currentTab, setCurrentTab] = useState(0);
3936

37+
const tabs = [
38+
{
39+
label: t("explainers:label.globalExplanations"),
40+
value: 0,
41+
disabled: false,
42+
},
43+
{
44+
label: t("explainers:label.localExplanations"),
45+
value: 1,
46+
disabled: false,
47+
},
48+
];
49+
4050
const handleTabChange = (event, newValue) => {
4151
setCurrentTab(newValue);
4252
};
@@ -46,7 +56,12 @@ export default function ExplainersDashboard() {
4656
taskName: taskName,
4757
};
4858

49-
const ExplainersTable = ({ scope, handleNewExplainer, description }) => {
59+
const ExplainersTable = ({
60+
scope,
61+
title,
62+
handleNewExplainer,
63+
description,
64+
}) => {
5065
return (
5166
<Grid size={{ xs: 12 }}>
5267
<Paper sx={{ py: 2, px: 2 }}>
@@ -58,7 +73,7 @@ export default function ExplainersDashboard() {
5873
sx={{ mb: 4 }}
5974
>
6075
<Typography variant="h4" component="h2">
61-
{scope.charAt(0).toUpperCase() + scope.slice(1)} explanations
76+
{title}
6277
</Typography>
6378
<Grid>
6479
<TimestampWrapper
@@ -73,7 +88,7 @@ export default function ExplainersDashboard() {
7388
onClick={handleNewExplainer}
7489
endIcon={<AddIcon />}
7590
>
76-
Add {scope} Explainer
91+
{t("explainers:button.addExplainer")}
7792
</Button>
7893
</TimestampWrapper>
7994
</Grid>
@@ -105,11 +120,12 @@ export default function ExplainersDashboard() {
105120
explainerConfig={explainerConfig}
106121
/>
107122
<Typography variant="h4" component="h1" sx={{ mb: 3 }}>
108-
Explanations dashboard for model {modelName}
123+
{t("explainers:label.explainersDashboardTitle", {
124+
modelName: modelName,
125+
})}
109126
</Typography>
110127
<Typography variant="h6" component="h1" sx={{ mb: 3 }}>
111-
Configure global or local explainers for your trained model to explore
112-
and understand its decision-making process.
128+
{t("explainers:label.explainersDashboardDescription")}
113129
</Typography>
114130
<TimestampWrapper eventName={TIMESTAMP_KEYS.explainer.leavingDashboard}>
115131
<Button
@@ -118,7 +134,7 @@ export default function ExplainersDashboard() {
118134
navigate(`/app/explainers`);
119135
}}
120136
>
121-
Return to table
137+
{t("explainers:button.backToExplainers")}
122138
</Button>
123139
</TimestampWrapper>
124140

@@ -136,19 +152,17 @@ export default function ExplainersDashboard() {
136152
{currentTab === 0 && (
137153
<ExplainersTable
138154
scope={"global"}
155+
title={t("explainers:label.globalExplanations")}
139156
handleNewExplainer={handleNewGlobalExplainerModal}
140-
description={
141-
"Global explanations describe how the overall machine learning model works."
142-
}
157+
description={t("explainers:label.globalExplanationsDescription")}
143158
/>
144159
)}
145160
{currentTab === 1 && (
146161
<ExplainersTable
147162
scope={"local"}
163+
title={t("explainers:label.localExplanations")}
148164
handleNewExplainer={handleNewLocalExplainerModal}
149-
description={
150-
"Local explanations explain model predictions for an specific instance."
151-
}
165+
description={t("explainers:label.localExplanationsDescription")}
152166
/>
153167
)}
154168
</Grid>

DashAI/front/src/components/explainers/ExplainersGrid.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { getExplainers as getExplainersRequest } from "../../api/explainer";
77
import ExplainersCard from "./ExplanainersCard";
88
import useUpdateFlag from "../../hooks/useUpdateFlag";
99
import { flags } from "../../constants/flags";
10+
import { useTranslation } from "react-i18next";
1011

1112
/**
1213
* GlobalExplainersGrid
@@ -17,6 +18,7 @@ export default function ExplainersGrid(explainerConfig) {
1718
// const [loading, setLoading] = useState(false);
1819
const [explainers, setExplainers] = useState([]);
1920
const { runId, scope } = explainerConfig;
21+
const { t } = useTranslation(["explainers"]);
2022

2123
// Filter explainers that have status FINISHED
2224
function getFilteredExplainers(explainers) {
@@ -28,7 +30,9 @@ export default function ExplainersGrid(explainerConfig) {
2830
const explainers = await getExplainersRequest(runId, scope);
2931
setExplainers(explainers);
3032
} catch (error) {
31-
enqueueSnackbar("Error while trying to obtain the explainers.");
33+
enqueueSnackbar(t("explainers:error.fetchExplainers"), {
34+
variant: "error",
35+
});
3236
if (error.response) {
3337
console.error("Response error:", error.message);
3438
} else if (error.request) {

DashAI/front/src/components/explainers/ExplainersPlot.jsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ import PropTypes from "prop-types";
55
import { useSnackbar } from "notistack";
66

77
import { getExplainerPlot as getExplainerPlotRequest } from "../../api/explainer";
8+
import { useTranslation } from "react-i18next";
89

910
export default function ExplainersPlot({ explainer, scope }) {
1011
const { enqueueSnackbar } = useSnackbar();
1112
const [explainersPlots, setExplainersPlots] = useState([]);
1213
const [currentPlot, setCurrentPlot] = useState(0);
1314
const [loading, setLoading] = useState(true);
1415
const isLocal = scope === "local";
16+
const { t } = useTranslation(["explainers"]);
1517
function parseExplanationPlot(explanation) {
1618
const formattedPlot = JSON.parse(JSON.stringify(explanation));
1719
return formattedPlot.map(JSON.parse);
@@ -27,7 +29,9 @@ export default function ExplainersPlot({ explainer, scope }) {
2729
const parsedExplainersPlot = parseExplanationPlot(explainersPlots);
2830
setExplainersPlots(parsedExplainersPlot);
2931
} catch (error) {
30-
enqueueSnackbar("Error while trying to obtain the explainers.");
32+
enqueueSnackbar(t("explainers:error.fetchExplainers"), {
33+
variant: "error",
34+
});
3135
if (error.response) {
3236
console.error("Response error:", error.message);
3337
} else if (error.request) {
@@ -59,7 +63,7 @@ export default function ExplainersPlot({ explainer, scope }) {
5963
>
6064
{explainersPlots.map((_, i) => (
6165
<MenuItem key={i} value={i}>
62-
Instance {i + 1}
66+
{t("explainers:label.instanceNumber", { number: i + 1 })}
6367
</MenuItem>
6468
))}
6569
</Select>

0 commit comments

Comments
 (0)