translated hard-code English words to match selected language system, e.g., german, french and italian

This commit is contained in:
Yinyin Liu 2026-03-09 11:23:09 +01:00
parent 66803a2b34
commit 2e52b9ee15
34 changed files with 423 additions and 145 deletions

View File

@ -19,6 +19,7 @@ import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
import axiosConfig from 'src/Resources/axiosConfig'; import axiosConfig from 'src/Resources/axiosConfig';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import routes from 'src/Resources/routes.json'; import routes from 'src/Resources/routes.json';
import { FormattedMessage, useIntl } from 'react-intl';
interface ForgotPasswordPromps { interface ForgotPasswordPromps {
resetPassword: () => void; resetPassword: () => void;
@ -29,6 +30,7 @@ function ForgotPassword() {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [errorModalOpen, setErrorModalOpen] = useState(false); const [errorModalOpen, setErrorModalOpen] = useState(false);
const intl = useIntl();
const theme = useTheme(); const theme = useTheme();
const context = useContext(UserContext); const context = useContext(UserContext);
@ -105,7 +107,7 @@ function ForgotPassword() {
<LockOutlinedIcon /> <LockOutlinedIcon />
</Avatar> </Avatar>
<Typography component="h1" variant="h5"> <Typography component="h1" variant="h5">
Provide your username <FormattedMessage id="provideYourUsername" defaultMessage="Provide your username" />
</Typography> </Typography>
<Box <Box
component="form" component="form"
@ -118,7 +120,7 @@ function ForgotPassword() {
}} }}
> >
<TextField <TextField
label="User Name" label={intl.formatMessage({ id: 'userName', defaultMessage: 'User Name' })}
variant="outlined" variant="outlined"
type="username" type="username"
value={username} value={username}
@ -150,7 +152,7 @@ function ForgotPassword() {
color="primary" color="primary"
onClick={handleSubmit} onClick={handleSubmit}
> >
Submit <FormattedMessage id="submit" defaultMessage="Submit" />
</Button> </Button>
<Modal <Modal
@ -176,7 +178,7 @@ function ForgotPassword() {
}} }}
> >
<Typography variant="body1" gutterBottom> <Typography variant="body1" gutterBottom>
Username is wrong. Please try again. <FormattedMessage id="usernameWrong" defaultMessage="Username is wrong. Please try again." />
</Typography> </Typography>
<Button <Button
sx={{ sx={{
@ -188,7 +190,7 @@ function ForgotPassword() {
}} }}
onClick={() => setErrorModalOpen(false)} onClick={() => setErrorModalOpen(false)}
> >
Close <FormattedMessage id="close" defaultMessage="Close" />
</Button> </Button>
</Box> </Box>
</Modal> </Modal>
@ -216,7 +218,7 @@ function ForgotPassword() {
}} }}
> >
<Typography variant="body1" gutterBottom> <Typography variant="body1" gutterBottom>
Mail sent successfully. <FormattedMessage id="mailSentSuccessfully" defaultMessage="Mail sent successfully." />
</Typography> </Typography>
<Button <Button
sx={{ sx={{
@ -228,7 +230,7 @@ function ForgotPassword() {
}} }}
onClick={handleReturn} onClick={handleReturn}
> >
Close <FormattedMessage id="close" defaultMessage="Close" />
</Button> </Button>
</Box> </Box>
</Modal> </Modal>

View File

@ -18,12 +18,14 @@ import { TokenContext } from 'src/contexts/tokenContext';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import Avatar from '@mui/material/Avatar'; import Avatar from '@mui/material/Avatar';
import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
import { FormattedMessage, useIntl } from 'react-intl';
function ResetPassword() { function ResetPassword() {
const [username, setUsername] = useState(''); const [username, setUsername] = useState('');
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [rememberMe, setRememberMe] = useState(false); const [rememberMe, setRememberMe] = useState(false);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const intl = useIntl();
const theme = useTheme(); const theme = useTheme();
const context = useContext(UserContext); const context = useContext(UserContext);
const navigate = useNavigate(); const navigate = useNavigate();
@ -102,7 +104,7 @@ function ResetPassword() {
<LockOutlinedIcon /> <LockOutlinedIcon />
</Avatar> </Avatar>
<Typography component="h1" variant="h5"> <Typography component="h1" variant="h5">
Reset Password <FormattedMessage id="resetPassword" defaultMessage="Reset Password" />
</Typography> </Typography>
<Box <Box
component="form" component="form"
@ -115,7 +117,7 @@ function ResetPassword() {
}} }}
> >
<TextField <TextField
label="Password" label={intl.formatMessage({ id: 'password', defaultMessage: 'Password' })}
variant="outlined" variant="outlined"
type="password" type="password"
value={password} value={password}
@ -126,7 +128,7 @@ function ResetPassword() {
sx={{ width: 350 }} sx={{ width: 350 }}
/> />
<TextField <TextField
label="Verify Password" label={intl.formatMessage({ id: 'verifyPassword', defaultMessage: 'Verify Password' })}
type="password" type="password"
variant="outlined" variant="outlined"
value={verifypassword} value={verifypassword}
@ -147,7 +149,7 @@ function ResetPassword() {
variant="h5" variant="h5"
sx={{ color: '#FF0000', marginTop: 1 }} sx={{ color: '#FF0000', marginTop: 1 }}
> >
Passwords do not match <FormattedMessage id="passwordsDoNotMatch" defaultMessage="Passwords do not match" />
</Typography> </Typography>
)} )}
@ -164,7 +166,7 @@ function ResetPassword() {
color="primary" color="primary"
onClick={handleSubmit} onClick={handleSubmit}
> >
Submit <FormattedMessage id="submit" defaultMessage="Submit" />
</Button> </Button>
<Modal <Modal
@ -190,7 +192,7 @@ function ResetPassword() {
}} }}
> >
<Typography variant="body1" gutterBottom> <Typography variant="body1" gutterBottom>
Reset Password failed. Please try again. <FormattedMessage id="resetPasswordFailed" defaultMessage="Reset Password failed. Please try again." />
</Typography> </Typography>
<Button <Button
sx={{ sx={{
@ -202,7 +204,7 @@ function ResetPassword() {
}} }}
onClick={() => setOpen(false)} onClick={() => setOpen(false)}
> >
Close <FormattedMessage id="close" defaultMessage="Close" />
</Button> </Button>
</Box> </Box>
</Modal> </Modal>

View File

@ -18,12 +18,14 @@ import { TokenContext } from 'src/contexts/tokenContext';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import Avatar from '@mui/material/Avatar'; import Avatar from '@mui/material/Avatar';
import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
import { FormattedMessage, useIntl } from 'react-intl';
function SetNewPassword() { function SetNewPassword() {
const [username, setUsername] = useState(''); const [username, setUsername] = useState('');
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [rememberMe, setRememberMe] = useState(false); const [rememberMe, setRememberMe] = useState(false);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const intl = useIntl();
const theme = useTheme(); const theme = useTheme();
const context = useContext(UserContext); const context = useContext(UserContext);
const navigate = useNavigate(); const navigate = useNavigate();
@ -103,7 +105,7 @@ function SetNewPassword() {
<LockOutlinedIcon /> <LockOutlinedIcon />
</Avatar> </Avatar>
<Typography component="h1" variant="h5"> <Typography component="h1" variant="h5">
Set New Password <FormattedMessage id="setNewPassword" defaultMessage="Set New Password" />
</Typography> </Typography>
<Box <Box
component="form" component="form"
@ -116,7 +118,7 @@ function SetNewPassword() {
}} }}
> >
<TextField <TextField
label="Password" label={intl.formatMessage({ id: 'password', defaultMessage: 'Password' })}
variant="outlined" variant="outlined"
type="password" type="password"
value={password} value={password}
@ -127,7 +129,7 @@ function SetNewPassword() {
sx={{ width: 350 }} sx={{ width: 350 }}
/> />
<TextField <TextField
label="Verify Password" label={intl.formatMessage({ id: 'verifyPassword', defaultMessage: 'Verify Password' })}
type="password" type="password"
variant="outlined" variant="outlined"
value={verifypassword} value={verifypassword}
@ -148,7 +150,7 @@ function SetNewPassword() {
variant="h5" variant="h5"
sx={{ color: '#FF0000', marginTop: 1 }} sx={{ color: '#FF0000', marginTop: 1 }}
> >
Passwords do not match <FormattedMessage id="passwordsDoNotMatch" defaultMessage="Passwords do not match" />
</Typography> </Typography>
)} )}
@ -165,7 +167,7 @@ function SetNewPassword() {
color="primary" color="primary"
onClick={handleSubmit} onClick={handleSubmit}
> >
Submit <FormattedMessage id="submit" defaultMessage="Submit" />
</Button> </Button>
<Modal <Modal
@ -191,7 +193,7 @@ function SetNewPassword() {
}} }}
> >
<Typography variant="body1" gutterBottom> <Typography variant="body1" gutterBottom>
Setting new password failed. Please try again. <FormattedMessage id="setNewPasswordFailed" defaultMessage="Setting new password failed. Please try again." />
</Typography> </Typography>
<Button <Button
sx={{ sx={{
@ -203,7 +205,7 @@ function SetNewPassword() {
}} }}
onClick={() => setOpen(false)} onClick={() => setOpen(false)}
> >
Close <FormattedMessage id="close" defaultMessage="Close" />
</Button> </Button>
</Box> </Box>
</Modal> </Modal>

View File

@ -25,6 +25,7 @@ import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';
import CheckBoxIcon from '@mui/icons-material/CheckBox'; import CheckBoxIcon from '@mui/icons-material/CheckBox';
import routes from 'src/Resources/routes.json'; import routes from 'src/Resources/routes.json';
import { ProductIdContext } from '../contexts/ProductIdContextProvider'; import { ProductIdContext } from '../contexts/ProductIdContextProvider';
import { FormattedMessage, useIntl } from 'react-intl';
function Login() { function Login() {
const [username, setUsername] = useState(''); const [username, setUsername] = useState('');
@ -34,6 +35,7 @@ function Login() {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [error, setError] = useState(false); const [error, setError] = useState(false);
const intl = useIntl();
const theme = useTheme(); const theme = useTheme();
const context = useContext(UserContext); const context = useContext(UserContext);
const { const {
@ -147,7 +149,7 @@ function Login() {
<LockOutlinedIcon /> <LockOutlinedIcon />
</Avatar> </Avatar>
<Typography component="h1" variant="h5"> <Typography component="h1" variant="h5">
Sign in <FormattedMessage id="signIn" defaultMessage="Sign in" />
</Typography> </Typography>
<Box <Box
component="form" component="form"
@ -160,7 +162,7 @@ function Login() {
}} }}
> >
<TextField <TextField
label="Username" label={intl.formatMessage({ id: 'username', defaultMessage: 'Username' })}
value={username} value={username}
onChange={handleUsernameChange} onChange={handleUsernameChange}
fullWidth fullWidth
@ -176,7 +178,7 @@ function Login() {
/> />
<TextField <TextField
label="Password" label={intl.formatMessage({ id: 'password', defaultMessage: 'Password' })}
variant="outlined" variant="outlined"
type="password" type="password"
value={password} value={password}
@ -203,7 +205,7 @@ function Login() {
style={{ marginLeft: -175 }} style={{ marginLeft: -175 }}
/> />
} }
label="Remember me" label={<FormattedMessage id="rememberMe" defaultMessage="Remember me" />}
/> />
<Button <Button
@ -218,7 +220,7 @@ function Login() {
color="primary" color="primary"
onClick={handleSubmit} onClick={handleSubmit}
> >
Login <FormattedMessage id="login" defaultMessage="Login" />
</Button> </Button>
{loading && ( {loading && (
@ -253,7 +255,7 @@ function Login() {
}} }}
> >
<Typography variant="body1" gutterBottom> <Typography variant="body1" gutterBottom>
Login failed. Please try again. <FormattedMessage id="loginFailed" defaultMessage="Login failed. Please try again." />
</Typography> </Typography>
<Button <Button
sx={{ sx={{
@ -265,7 +267,7 @@ function Login() {
}} }}
onClick={() => setOpen(false)} onClick={() => setOpen(false)}
> >
Close <FormattedMessage id="close" defaultMessage="Close" />
</Button> </Button>
</Box> </Box>
</Modal> </Modal>
@ -281,7 +283,7 @@ function Login() {
onForgotPassword(); onForgotPassword();
}} }}
> >
Forgot password? <FormattedMessage id="forgotPasswordLink" defaultMessage="Forgot password?" />
</Link> </Link>
</Grid> </Grid>
</Grid> </Grid>

View File

@ -87,10 +87,10 @@ function BatteryView(props: BatteryViewProps) {
style={{ color: 'black', fontWeight: 'bold' }} style={{ color: 'black', fontWeight: 'bold' }}
mt={2} mt={2}
> >
Unable to communicate with the installation <FormattedMessage id="unableToCommunicate" defaultMessage="Unable to communicate with the installation" />
</Typography> </Typography>
<Typography variant="body2" style={{ color: 'black' }}> <Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page <FormattedMessage id="pleaseWaitOrRefresh" defaultMessage="Please wait or refresh the page" />
</Typography> </Typography>
</Container> </Container>
)} )}
@ -111,10 +111,10 @@ function BatteryView(props: BatteryViewProps) {
style={{ color: 'black', fontWeight: 'bold' }} style={{ color: 'black', fontWeight: 'bold' }}
mt={2} mt={2}
> >
Battery service is not available at the moment <FormattedMessage id="batteryServiceNotAvailable" defaultMessage="Battery service is not available at the moment" />
</Typography> </Typography>
<Typography variant="body2" style={{ color: 'black' }}> <Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page <FormattedMessage id="pleaseWaitOrRefresh" defaultMessage="Please wait or refresh the page" />
</Typography> </Typography>
</Container> </Container>
)} )}
@ -229,24 +229,24 @@ function BatteryView(props: BatteryViewProps) {
<Table sx={{ minWidth: 650 }} aria-label="simple table"> <Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead> <TableHead>
<TableRow> <TableRow>
<TableCell align="center">Battery</TableCell> <TableCell align="center"><FormattedMessage id="battery" defaultMessage="Battery" /></TableCell>
<TableCell align="center">Firmware</TableCell> <TableCell align="center"><FormattedMessage id="firmware" defaultMessage="Firmware" /></TableCell>
<TableCell align="center">Power</TableCell> <TableCell align="center"><FormattedMessage id="power" defaultMessage="Power" /></TableCell>
<TableCell align="center">Battery Voltage</TableCell> <TableCell align="center"><FormattedMessage id="batteryVoltage" defaultMessage="Battery Voltage" /></TableCell>
<TableCell align="center">SoC</TableCell> <TableCell align="center"><FormattedMessage id="soc" defaultMessage="SoC" /></TableCell>
<TableCell align="center">Temperature</TableCell> <TableCell align="center"><FormattedMessage id="temperature" defaultMessage="Temperature" /></TableCell>
{product === 0 ? ( {product === 0 ? (
<TableCell align="center">Warnings</TableCell> <TableCell align="center"><FormattedMessage id="warnings" defaultMessage="Warnings" /></TableCell>
) : ( ) : (
<TableCell align="center">Min Cell Voltage</TableCell> <TableCell align="center"><FormattedMessage id="minCellVoltage" defaultMessage="Min Cell Voltage" /></TableCell>
)} )}
{product === 0 ? ( {product === 0 ? (
<TableCell align="center">Alarms</TableCell> <TableCell align="center"><FormattedMessage id="alarms" defaultMessage="Alarms" /></TableCell>
) : ( ) : (
<TableCell align="center">Max Cell Voltage</TableCell> <TableCell align="center"><FormattedMessage id="maxCellVoltage" defaultMessage="Max Cell Voltage" /></TableCell>
)} )}
{(product === 3 || product === 4) && ( {(product === 3 || product === 4) && (
<TableCell align="center">Voltage Difference</TableCell> <TableCell align="center"><FormattedMessage id="voltageDifference" defaultMessage="Voltage Difference" /></TableCell>
)} )}
</TableRow> </TableRow>
</TableHead> </TableHead>

View File

@ -85,10 +85,10 @@ function BatteryViewSalidomo(props: BatteryViewProps) {
style={{ color: 'black', fontWeight: 'bold' }} style={{ color: 'black', fontWeight: 'bold' }}
mt={2} mt={2}
> >
Unable to communicate with the installation <FormattedMessage id="unableToCommunicate" defaultMessage="Unable to communicate with the installation" />
</Typography> </Typography>
<Typography variant="body2" style={{ color: 'black' }}> <Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page <FormattedMessage id="pleaseWaitOrRefresh" defaultMessage="Please wait or refresh the page" />
</Typography> </Typography>
</Container> </Container>
)} )}
@ -109,10 +109,10 @@ function BatteryViewSalidomo(props: BatteryViewProps) {
style={{ color: 'black', fontWeight: 'bold' }} style={{ color: 'black', fontWeight: 'bold' }}
mt={2} mt={2}
> >
Battery service is not available at the moment <FormattedMessage id="batteryServiceNotAvailable" defaultMessage="Battery service is not available at the moment" />
</Typography> </Typography>
<Typography variant="body2" style={{ color: 'black' }}> <Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page <FormattedMessage id="pleaseWaitOrRefresh" defaultMessage="Please wait or refresh the page" />
</Typography> </Typography>
</Container> </Container>
)} )}
@ -209,14 +209,14 @@ function BatteryViewSalidomo(props: BatteryViewProps) {
<Table sx={{ minWidth: 650 }} aria-label="simple table"> <Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead> <TableHead>
<TableRow> <TableRow>
<TableCell align="center">Battery</TableCell> <TableCell align="center"><FormattedMessage id="battery" defaultMessage="Battery" /></TableCell>
<TableCell align="center">Firmware</TableCell> <TableCell align="center"><FormattedMessage id="firmware" defaultMessage="Firmware" /></TableCell>
<TableCell align="center">Power</TableCell> <TableCell align="center"><FormattedMessage id="power" defaultMessage="Power" /></TableCell>
<TableCell align="center">Voltage</TableCell> <TableCell align="center"><FormattedMessage id="voltage" defaultMessage="Voltage" /></TableCell>
<TableCell align="center">SoC</TableCell> <TableCell align="center"><FormattedMessage id="soc" defaultMessage="SoC" /></TableCell>
<TableCell align="center">Temperature</TableCell> <TableCell align="center"><FormattedMessage id="temperature" defaultMessage="Temperature" /></TableCell>
<TableCell align="center">Warnings</TableCell> <TableCell align="center"><FormattedMessage id="warnings" defaultMessage="Warnings" /></TableCell>
<TableCell align="center">Alarms</TableCell> <TableCell align="center"><FormattedMessage id="alarms" defaultMessage="Alarms" /></TableCell>
</TableRow> </TableRow>
</TableHead> </TableHead>
<TableBody> <TableBody>

View File

@ -87,10 +87,10 @@ function BatteryViewSodioHome(props: BatteryViewSodioHomeProps) {
style={{ color: 'black', fontWeight: 'bold' }} style={{ color: 'black', fontWeight: 'bold' }}
mt={2} mt={2}
> >
Unable to communicate with the installation <FormattedMessage id="unableToCommunicate" defaultMessage="Unable to communicate with the installation" />
</Typography> </Typography>
<Typography variant="body2" style={{ color: 'black' }}> <Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page <FormattedMessage id="pleaseWaitOrRefresh" defaultMessage="Please wait or refresh the page" />
</Typography> </Typography>
</Container> </Container>
)} )}
@ -111,10 +111,10 @@ function BatteryViewSodioHome(props: BatteryViewSodioHomeProps) {
style={{ color: 'black', fontWeight: 'bold' }} style={{ color: 'black', fontWeight: 'bold' }}
mt={2} mt={2}
> >
Battery service is not available at the moment <FormattedMessage id="batteryServiceNotAvailable" defaultMessage="Battery service is not available at the moment" />
</Typography> </Typography>
<Typography variant="body2" style={{ color: 'black' }}> <Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page <FormattedMessage id="pleaseWaitOrRefresh" defaultMessage="Please wait or refresh the page" />
</Typography> </Typography>
</Container> </Container>
)} )}
@ -195,12 +195,12 @@ function BatteryViewSodioHome(props: BatteryViewSodioHomeProps) {
<Table sx={{ minWidth: 650 }} aria-label="simple table"> <Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead> <TableHead>
<TableRow> <TableRow>
<TableCell align="center">Battery</TableCell> <TableCell align="center"><FormattedMessage id="battery" defaultMessage="Battery" /></TableCell>
<TableCell align="center">Power</TableCell> <TableCell align="center"><FormattedMessage id="power" defaultMessage="Power" /></TableCell>
<TableCell align="center">Battery Voltage</TableCell> <TableCell align="center"><FormattedMessage id="batteryVoltage" defaultMessage="Battery Voltage" /></TableCell>
<TableCell align="center">Current</TableCell> <TableCell align="center"><FormattedMessage id="current" defaultMessage="Current" /></TableCell>
<TableCell align="center">SoC</TableCell> <TableCell align="center"><FormattedMessage id="soc" defaultMessage="SoC" /></TableCell>
<TableCell align="center">SoH</TableCell> <TableCell align="center"><FormattedMessage id="soh" defaultMessage="SoH" /></TableCell>
{/*<TableCell align="center">Daily Charge Energy</TableCell>*/} {/*<TableCell align="center">Daily Charge Energy</TableCell>*/}
{/*<TableCell align="center">Daily Discharge Energy</TableCell>*/} {/*<TableCell align="center">Daily Discharge Energy</TableCell>*/}
</TableRow> </TableRow>

View File

@ -295,7 +295,7 @@ function MainStats(props: MainStatsProps) {
> >
<CircularProgress size={60} style={{ color: '#ffc04d' }} /> <CircularProgress size={60} style={{ color: '#ffc04d' }} />
<Typography variant="body2" style={{ color: 'black' }} mt={2}> <Typography variant="body2" style={{ color: 'black' }} mt={2}>
Fetching data... <FormattedMessage id="fetchingData" defaultMessage="Fetching data..." />
</Typography> </Typography>
</Container> </Container>
)} )}

View File

@ -294,7 +294,7 @@ function MainStatsSalidomo(props: MainStatsProps) {
> >
<CircularProgress size={60} style={{ color: '#ffc04d' }} /> <CircularProgress size={60} style={{ color: '#ffc04d' }} />
<Typography variant="body2" style={{ color: 'black' }} mt={2}> <Typography variant="body2" style={{ color: 'black' }} mt={2}>
Fetching data... <FormattedMessage id="fetchingData" defaultMessage="Fetching data..." />
</Typography> </Typography>
</Container> </Container>
)} )}

View File

@ -302,7 +302,7 @@ function MainStatsSodioHome(props: MainStatsSodioHomeProps) {
> >
<CircularProgress size={60} style={{ color: '#ffc04d' }} /> <CircularProgress size={60} style={{ color: '#ffc04d' }} />
<Typography variant="body2" style={{ color: 'black' }} mt={2}> <Typography variant="body2" style={{ color: 'black' }} mt={2}>
Fetching data... <FormattedMessage id="fetchingData" defaultMessage="Fetching data..." />
</Typography> </Typography>
</Container> </Container>
)} )}

View File

@ -19,7 +19,7 @@ import {
} from '@mui/material'; } from '@mui/material';
import React, { useContext, useState } from 'react'; import React, { useContext, useState } from 'react';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
import { Close as CloseIcon } from '@mui/icons-material'; import { Close as CloseIcon } from '@mui/icons-material';
import MenuItem from '@mui/material/MenuItem'; import MenuItem from '@mui/material/MenuItem';
@ -40,6 +40,7 @@ interface ConfigurationProps {
} }
function Configuration(props: ConfigurationProps) { function Configuration(props: ConfigurationProps) {
const intl = useIntl();
if (props.values === null) { if (props.values === null) {
return null; return null;
} }
@ -137,7 +138,7 @@ function Configuration(props: ConfigurationProps) {
props.values.EssControl.Mode === 'CalibrationCharge' props.values.EssControl.Mode === 'CalibrationCharge'
) { ) {
setDateSelectionError( setDateSelectionError(
'You cannot change the date while the installation is in Calibration Charge Mode' intl.formatMessage({ id: 'cannotChangeDateCalibration' })
); );
setErrorDateModalOpen(true); setErrorDateModalOpen(true);
return; return;
@ -146,7 +147,7 @@ function Configuration(props: ConfigurationProps) {
dayjs(formValues.calibrationChargeDate).isBefore(dayjs()) dayjs(formValues.calibrationChargeDate).isBefore(dayjs())
) { ) {
//console.log('asked for', dayjs(formValues.calibrationChargeDate)); //console.log('asked for', dayjs(formValues.calibrationChargeDate));
setDateSelectionError('You must specify a future date'); setDateSelectionError(intl.formatMessage({ id: 'mustSpecifyFutureDate' }));
setErrorDateModalOpen(true); setErrorDateModalOpen(true);
return; return;
} else { } else {
@ -458,7 +459,7 @@ function Configuration(props: ConfigurationProps) {
helperText={ helperText={
errors.minimumSoC ? ( errors.minimumSoC ? (
<span style={{ color: 'red' }}> <span style={{ color: 'red' }}>
Value should be between 0-100% {intl.formatMessage({ id: 'valueBetween0And100' })}
</span> </span>
) : ( ) : (
'' ''
@ -592,7 +593,7 @@ function Configuration(props: ConfigurationProps) {
helperText={ helperText={
errors.gridSetPoint ? ( errors.gridSetPoint ? (
<span style={{ color: 'red' }}> <span style={{ color: 'red' }}>
Please provide a valid number {intl.formatMessage({ id: 'pleaseProvideValidNumber' })}
</span> </span>
) : ( ) : (
'' ''
@ -804,7 +805,7 @@ function Configuration(props: ConfigurationProps) {
alignItems: 'center' alignItems: 'center'
}} }}
> >
Successfully applied configuration file <FormattedMessage id="successfullyAppliedConfig" defaultMessage="Successfully applied configuration file" />
<IconButton <IconButton
color="inherit" color="inherit"
size="small" size="small"
@ -824,7 +825,7 @@ function Configuration(props: ConfigurationProps) {
alignItems: 'center' alignItems: 'center'
}} }}
> >
An error has occurred <FormattedMessage id="configErrorOccurred" defaultMessage="An error has occurred" />
<IconButton <IconButton
color="inherit" color="inherit"
size="small" size="small"

View File

@ -22,7 +22,7 @@ import {
import { I_Installation } from 'src/interfaces/InstallationTypes'; import { I_Installation } from 'src/interfaces/InstallationTypes';
import CancelIcon from '@mui/icons-material/Cancel'; import CancelIcon from '@mui/icons-material/Cancel';
import BuildIcon from '@mui/icons-material/Build'; import BuildIcon from '@mui/icons-material/Build';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
import { useLocation, useNavigate } from 'react-router-dom'; import { useLocation, useNavigate } from 'react-router-dom';
import routes from '../../../Resources/routes.json'; import routes from '../../../Resources/routes.json';
import { ProductIdContext } from '../../../contexts/ProductIdContextProvider'; import { ProductIdContext } from '../../../contexts/ProductIdContextProvider';
@ -33,6 +33,7 @@ interface FlatInstallationViewProps {
} }
const FlatInstallationView = (props: FlatInstallationViewProps) => { const FlatInstallationView = (props: FlatInstallationViewProps) => {
const intl = useIntl();
const [isRowHovered, setHoveredRow] = useState(-1); const [isRowHovered, setHoveredRow] = useState(-1);
const navigate = useNavigate(); const navigate = useNavigate();
const [selectedInstallation, setSelectedInstallation] = useState<number>(-1); const [selectedInstallation, setSelectedInstallation] = useState<number>(-1);
@ -202,7 +203,7 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
> >
<FormControl sx={{ flex: 1 }}> <FormControl sx={{ flex: 1 }}>
<TextField <TextField
placeholder="Search" placeholder={intl.formatMessage({ id: 'search' })}
value={searchTerm} value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
fullWidth fullWidth
@ -226,7 +227,7 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
<Select <Select
value={sortByStatus} value={sortByStatus}
onChange={(e) => setSortByStatus(e.target.value)} onChange={(e) => setSortByStatus(e.target.value)}
label="Show Only" label={intl.formatMessage({ id: 'showOnly' })}
> >
{[ {[
'All Installations', 'All Installations',
@ -252,7 +253,7 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
<Select <Select
value={sortByAction} value={sortByAction}
onChange={(e) => setSortByAction(e.target.value)} onChange={(e) => setSortByAction(e.target.value)}
label="Show Only" label={intl.formatMessage({ id: 'showOnly' })}
> >
{[ {[
'All Installations', 'All Installations',

View File

@ -394,7 +394,7 @@ function Installation(props: singleInstallationProps) {
style={{ color: 'black', fontWeight: 'bold' }} style={{ color: 'black', fontWeight: 'bold' }}
mt={2} mt={2}
> >
Connecting to the device... <FormattedMessage id="connectingToDevice" defaultMessage="Connecting to the device..." />
</Typography> </Typography>
</Container> </Container>
)} )}

View File

@ -19,7 +19,7 @@ import {
transformInputToDailyDataJson transformInputToDailyDataJson
} from 'src/interfaces/Chart'; } from 'src/interfaces/Chart';
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
import CircularProgress from '@mui/material/CircularProgress'; import CircularProgress from '@mui/material/CircularProgress';
import { LocalizationProvider } from '@mui/x-date-pickers'; import { LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
@ -52,6 +52,7 @@ const computeLast7Days = (): string[] => {
}; };
function Overview(props: OverviewProps) { function Overview(props: OverviewProps) {
const intl = useIntl();
const context = useContext(UserContext); const context = useContext(UserContext);
const { currentUser } = context; const { currentUser } = context;
const [dailyData, setDailyData] = useState(true); const [dailyData, setDailyData] = useState(true);
@ -119,7 +120,7 @@ function Overview(props: OverviewProps) {
resultPromise resultPromise
.then((result) => { .then((result) => {
if (result.chartData.soc.data.length === 0) { if (result.chartData.soc.data.length === 0) {
setDateSelectionError('No data available for the selected date range. Please choose a more recent date.'); setDateSelectionError(intl.formatMessage({ id: 'noDataForDateRange' }));
setErrorDateModalOpen(true); setErrorDateModalOpen(true);
setLoading(false); setLoading(false);
return; return;
@ -288,7 +289,7 @@ function Overview(props: OverviewProps) {
resultPromise resultPromise
.then((result) => { .then((result) => {
if (result.chartData.soc.data.length === 0) { if (result.chartData.soc.data.length === 0) {
setDateSelectionError('No data available for the selected date range. Please choose a more recent date.'); setDateSelectionError(intl.formatMessage({ id: 'noDataForDateRange' }));
setErrorDateModalOpen(true); setErrorDateModalOpen(true);
setLoading(false); setLoading(false);
return; return;
@ -616,7 +617,7 @@ function Overview(props: OverviewProps) {
> >
<CircularProgress size={60} style={{ color: '#ffc04d' }} /> <CircularProgress size={60} style={{ color: '#ffc04d' }} />
<Typography variant="body2" style={{ color: 'black' }} mt={2}> <Typography variant="body2" style={{ color: 'black' }} mt={2}>
Fetching data... <FormattedMessage id="fetchingData" defaultMessage="Fetching data..." />
</Typography> </Typography>
</Container> </Container>
)} )}

View File

@ -405,7 +405,7 @@ const computeLast7Days = (): string[] => {
// > // >
// <CircularProgress size={60} style={{ color: '#ffc04d' }} /> // <CircularProgress size={60} style={{ color: '#ffc04d' }} />
// <Typography variant="body2" style={{ color: 'black' }} mt={2}> // <Typography variant="body2" style={{ color: 'black' }} mt={2}>
// Fetching data... // <FormattedMessage id="fetchingData" defaultMessage="Fetching data..." />
// </Typography> // </Typography>
// </Container> // </Container>
// )} // )}
@ -945,7 +945,7 @@ function SalidomoOverview(props: salidomoOverviewProps) {
> >
<CircularProgress size={60} style={{ color: '#ffc04d' }} /> <CircularProgress size={60} style={{ color: '#ffc04d' }} />
<Typography variant="body2" style={{ color: 'black' }} mt={2}> <Typography variant="body2" style={{ color: 'black' }} mt={2}>
Fetching data... <FormattedMessage id="fetchingData" defaultMessage="Fetching data..." />
</Typography> </Typography>
</Container> </Container>
)} )}

View File

@ -14,6 +14,7 @@ import { JSONRecordData } from '../Log/graph.util';
import { useLocation, useNavigate } from 'react-router-dom'; import { useLocation, useNavigate } from 'react-router-dom';
import routes from '../../../Resources/routes.json'; import routes from '../../../Resources/routes.json';
import CircularProgress from '@mui/material/CircularProgress'; import CircularProgress from '@mui/material/CircularProgress';
import { FormattedMessage } from 'react-intl';
interface PvViewProps { interface PvViewProps {
values: JSONRecordData; values: JSONRecordData;
@ -80,10 +81,10 @@ function PvView(props: PvViewProps) {
style={{ color: 'black', fontWeight: 'bold' }} style={{ color: 'black', fontWeight: 'bold' }}
mt={2} mt={2}
> >
Unable to communicate with the installation <FormattedMessage id="unableToCommunicate" defaultMessage="Unable to communicate with the installation" />
</Typography> </Typography>
<Typography variant="body2" style={{ color: 'black' }}> <Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page <FormattedMessage id="pleaseWaitOrRefresh" defaultMessage="Please wait or refresh the page" />
</Typography> </Typography>
</Container> </Container>
)} )}
@ -105,10 +106,10 @@ function PvView(props: PvViewProps) {
style={{ color: 'black', fontWeight: 'bold' }} style={{ color: 'black', fontWeight: 'bold' }}
mt={2} mt={2}
> >
Pv view is not available at the moment <FormattedMessage id="pvViewNotAvailable" defaultMessage="Pv view is not available at the moment" />
</Typography> </Typography>
<Typography variant="body2" style={{ color: 'black' }}> <Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page <FormattedMessage id="pleaseWaitOrRefresh" defaultMessage="Please wait or refresh the page" />
</Typography> </Typography>
</Container> </Container>
)} )}
@ -130,10 +131,10 @@ function PvView(props: PvViewProps) {
<Table sx={{ minWidth: 250 }} aria-label={`CU${deviceId} table`}> <Table sx={{ minWidth: 250 }} aria-label={`CU${deviceId} table`}>
<TableHead> <TableHead>
<TableRow> <TableRow>
<TableCell align="center">Pv</TableCell> <TableCell align="center"><FormattedMessage id="pv" defaultMessage="Pv" /></TableCell>
<TableCell align="center">Power</TableCell> <TableCell align="center"><FormattedMessage id="power" defaultMessage="Power" /></TableCell>
<TableCell align="center">Voltage</TableCell> <TableCell align="center"><FormattedMessage id="voltage" defaultMessage="Voltage" /></TableCell>
<TableCell align="center">Current</TableCell> <TableCell align="center"><FormattedMessage id="current" defaultMessage="Current" /></TableCell>
</TableRow> </TableRow>
</TableHead> </TableHead>
<TableBody> <TableBody>

View File

@ -20,7 +20,7 @@ import {
useTheme useTheme
} from '@mui/material'; } from '@mui/material';
import { I_Installation } from 'src/interfaces/InstallationTypes'; import { I_Installation } from 'src/interfaces/InstallationTypes';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
import { useLocation, useNavigate } from 'react-router-dom'; import { useLocation, useNavigate } from 'react-router-dom';
import routes from '../../../Resources/routes.json'; import routes from '../../../Resources/routes.json';
import CancelIcon from '@mui/icons-material/Cancel'; import CancelIcon from '@mui/icons-material/Cancel';
@ -32,6 +32,7 @@ interface FlatInstallationViewProps {
} }
const FlatInstallationView = (props: FlatInstallationViewProps) => { const FlatInstallationView = (props: FlatInstallationViewProps) => {
const intl = useIntl();
const navigate = useNavigate(); const navigate = useNavigate();
const [selectedInstallation, setSelectedInstallation] = useState<number>(-1); const [selectedInstallation, setSelectedInstallation] = useState<number>(-1);
const currentLocation = useLocation(); const currentLocation = useLocation();
@ -182,7 +183,7 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
> >
<FormControl sx={{ flex: 1 }}> <FormControl sx={{ flex: 1 }}>
<TextField <TextField
placeholder="Search" placeholder={intl.formatMessage({ id: 'search' })}
value={searchTerm} value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
fullWidth fullWidth
@ -206,7 +207,7 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
<Select <Select
value={sortByStatus} value={sortByStatus}
onChange={(e) => setSortByStatus(e.target.value)} onChange={(e) => setSortByStatus(e.target.value)}
label="Show Only" label={intl.formatMessage({ id: 'showOnly' })}
> >
{[ {[
'All Installations', 'All Installations',
@ -232,7 +233,7 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
<Select <Select
value={sortByAction} value={sortByAction}
onChange={(e) => setSortByAction(e.target.value)} onChange={(e) => setSortByAction(e.target.value)}
label="Show Only" label={intl.formatMessage({ id: 'showOnly' })}
> >
{[ {[
'All Installations', 'All Installations',

View File

@ -315,7 +315,7 @@ function SalidomoInstallation(props: singleInstallationProps) {
style={{ color: 'black', fontWeight: 'bold' }} style={{ color: 'black', fontWeight: 'bold' }}
mt={2} mt={2}
> >
Connecting to the device... <FormattedMessage id="connectingToDevice" defaultMessage="Connecting to the device..." />
</Typography> </Typography>
</Container> </Container>
)} )}

View File

@ -449,7 +449,7 @@ function SodioHomeInstallation(props: singleInstallationProps) {
style={{ color: 'black', fontWeight: 'bold' }} style={{ color: 'black', fontWeight: 'bold' }}
mt={2} mt={2}
> >
Connecting to the device... <FormattedMessage id="connectingToDevice" defaultMessage="Connecting to the device..." />
</Typography> </Typography>
</Container> </Container>
)} )}

View File

@ -1,6 +1,7 @@
import React, { useMemo, useState } from 'react'; import React, { useMemo, useState } from 'react';
import { FormControl, Grid, InputAdornment, TextField } from '@mui/material'; import { FormControl, Grid, InputAdornment, TextField } from '@mui/material';
import SearchTwoToneIcon from '@mui/icons-material/SearchTwoTone'; import SearchTwoToneIcon from '@mui/icons-material/SearchTwoTone';
import { useIntl } from 'react-intl';
import { I_Installation } from '../../../interfaces/InstallationTypes'; import { I_Installation } from '../../../interfaces/InstallationTypes';
import { Route, Routes, useLocation } from 'react-router-dom'; import { Route, Routes, useLocation } from 'react-router-dom';
import routes from '../../../Resources/routes.json'; import routes from '../../../Resources/routes.json';
@ -12,6 +13,7 @@ interface installationSearchProps {
} }
function InstallationSearch(props: installationSearchProps) { function InstallationSearch(props: installationSearchProps) {
const intl = useIntl();
const [searchTerm, setSearchTerm] = useState(''); const [searchTerm, setSearchTerm] = useState('');
const currentLocation = useLocation(); const currentLocation = useLocation();
// const [filteredData, setFilteredData] = useState(props.installations); // const [filteredData, setFilteredData] = useState(props.installations);
@ -60,7 +62,7 @@ function InstallationSearch(props: installationSearchProps) {
> >
<FormControl variant="outlined"> <FormControl variant="outlined">
<TextField <TextField
placeholder="Search" placeholder={intl.formatMessage({ id: 'search' })}
value={searchTerm} value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
fullWidth fullWidth

View File

@ -17,7 +17,7 @@ import {
} from '@mui/material'; } from '@mui/material';
import React, { useContext, useState, useEffect } from 'react'; import React, { useContext, useState, useEffect } from 'react';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
import { Close as CloseIcon } from '@mui/icons-material'; import { Close as CloseIcon } from '@mui/icons-material';
import MenuItem from '@mui/material/MenuItem'; import MenuItem from '@mui/material/MenuItem';
@ -39,6 +39,7 @@ interface SodistoreHomeConfigurationProps {
} }
function SodistoreHomeConfiguration(props: SodistoreHomeConfigurationProps) { function SodistoreHomeConfiguration(props: SodistoreHomeConfigurationProps) {
const intl = useIntl();
if (props.values === null) { if (props.values === null) {
return null; return null;
} }
@ -202,7 +203,7 @@ function SodistoreHomeConfiguration(props: SodistoreHomeConfigurationProps) {
const stopTimeInMinutes = stopHours * 60 + stopMinutes; const stopTimeInMinutes = stopHours * 60 + stopMinutes;
if (startTimeInMinutes >= stopTimeInMinutes) { if (startTimeInMinutes >= stopTimeInMinutes) {
setDateSelectionError('Stop time must be later than start time'); setDateSelectionError(intl.formatMessage({ id: 'stopTimeMustBeLater' }));
setErrorDateModalOpen(true); setErrorDateModalOpen(true);
return false; return false;
} }
@ -462,7 +463,7 @@ function SodistoreHomeConfiguration(props: SodistoreHomeConfigurationProps) {
{/* fullWidth*/} {/* fullWidth*/}
{/*/>*/} {/*/>*/}
<TextField <TextField
label="Minimum SoC (%)" label={intl.formatMessage({ id: 'minimumSocPercent' })}
name="minimumSoC" name="minimumSoC"
value={formValues.minimumSoC} value={formValues.minimumSoC}
onChange={handleChange} onChange={handleChange}
@ -540,13 +541,13 @@ function SodistoreHomeConfiguration(props: SodistoreHomeConfigurationProps) {
{/* Power input*/} {/* Power input*/}
<div style={{ marginBottom: '5px' }}> <div style={{ marginBottom: '5px' }}>
<TextField <TextField
label="Power (W)" label={intl.formatMessage({ id: 'powerW' })}
name="timeChargeandDischargePower" name="timeChargeandDischargePower"
value={formValues.timeChargeandDischargePower} value={formValues.timeChargeandDischargePower}
onChange={(e) => onChange={(e) =>
handleTimeChargeDischargeChange(e.target.name, e.target.value) handleTimeChargeDischargeChange(e.target.name, e.target.value)
} }
helperText="Enter a positive or negative power value" helperText={intl.formatMessage({ id: 'enterPowerValue' })}
fullWidth fullWidth
/> />
</div> </div>
@ -556,7 +557,7 @@ function SodistoreHomeConfiguration(props: SodistoreHomeConfigurationProps) {
<LocalizationProvider dateAdapter={AdapterDayjs}> <LocalizationProvider dateAdapter={AdapterDayjs}>
<DateTimePicker <DateTimePicker
ampm={false} ampm={false}
label="Start Date and Time (Start Time < Stop Time)" label={intl.formatMessage({ id: 'startDateTime' })}
value={ value={
formValues.startTimeChargeandDischargeDayandTime formValues.startTimeChargeandDischargeDayandTime
? dayjs(formValues.startTimeChargeandDischargeDayandTime) ? dayjs(formValues.startTimeChargeandDischargeDayandTime)
@ -588,7 +589,7 @@ function SodistoreHomeConfiguration(props: SodistoreHomeConfigurationProps) {
<LocalizationProvider dateAdapter={AdapterDayjs}> <LocalizationProvider dateAdapter={AdapterDayjs}>
<DateTimePicker <DateTimePicker
ampm={false} ampm={false}
label="Stop Date and Time (Start Time < Stop Time)" label={intl.formatMessage({ id: 'stopDateTime' })}
value={ value={
formValues.stopTimeChargeandDischargeDayandTime formValues.stopTimeChargeandDischargeDayandTime
? dayjs(formValues.stopTimeChargeandDischargeDayandTime) ? dayjs(formValues.stopTimeChargeandDischargeDayandTime)
@ -654,7 +655,7 @@ function SodistoreHomeConfiguration(props: SodistoreHomeConfigurationProps) {
alignItems: 'center' alignItems: 'center'
}} }}
> >
Successfully applied configuration file <FormattedMessage id="successfullyAppliedConfig" defaultMessage="Successfully applied configuration file" />
<IconButton <IconButton
color="inherit" color="inherit"
size="small" size="small"
@ -674,7 +675,7 @@ function SodistoreHomeConfiguration(props: SodistoreHomeConfigurationProps) {
alignItems: 'center' alignItems: 'center'
}} }}
> >
An error has occurred <FormattedMessage id="configErrorOccurred" defaultMessage="An error has occurred" />
<IconButton <IconButton
color="inherit" color="inherit"
size="small" size="small"

View File

@ -346,7 +346,7 @@ function WeeklySection({ installationId, latestMonthlyPeriodEnd }: { installatio
const msg = const msg =
err.response?.data || err.response?.data ||
err.message || err.message ||
'Failed to load report. Make sure the Excel file is placed in tmp_report/'; intl.formatMessage({ id: 'failedToLoadReport' });
setError(typeof msg === 'string' ? msg : JSON.stringify(msg)); setError(typeof msg === 'string' ? msg : JSON.stringify(msg));
} finally { } finally {
setLoading(false); setLoading(false);

View File

@ -13,6 +13,7 @@ import {
JSONRecordData JSONRecordData
} from '../Log/graph.util'; } from '../Log/graph.util';
import { ProductIdContext } from '../../../contexts/ProductIdContextProvider'; import { ProductIdContext } from '../../../contexts/ProductIdContextProvider';
import { FormattedMessage } from 'react-intl';
interface TopologyProps { interface TopologyProps {
values: JSONRecordData; values: JSONRecordData;
@ -64,10 +65,10 @@ function Topology(props: TopologyProps) {
style={{ color: 'black', fontWeight: 'bold' }} style={{ color: 'black', fontWeight: 'bold' }}
mt={2} mt={2}
> >
Unable to communicate with the installation <FormattedMessage id="unableToCommunicate" defaultMessage="Unable to communicate with the installation" />
</Typography> </Typography>
<Typography variant="body2" style={{ color: 'black' }}> <Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page <FormattedMessage id="pleaseWaitOrRefresh" defaultMessage="Please wait or refresh the page" />
</Typography> </Typography>
</Container> </Container>
)} )}

View File

@ -13,6 +13,7 @@ import {
JSONRecordData JSONRecordData
} from '../Log/graph.util'; } from '../Log/graph.util';
import { ProductIdContext } from '../../../contexts/ProductIdContextProvider'; import { ProductIdContext } from '../../../contexts/ProductIdContextProvider';
import { FormattedMessage } from 'react-intl';
interface TopologySodistoreHomeProps { interface TopologySodistoreHomeProps {
values: JSONRecordData; values: JSONRecordData;
@ -82,10 +83,10 @@ function TopologySodistoreHome(props: TopologySodistoreHomeProps) {
style={{ color: 'black', fontWeight: 'bold' }} style={{ color: 'black', fontWeight: 'bold' }}
mt={2} mt={2}
> >
Unable to communicate with the installation <FormattedMessage id="unableToCommunicate" defaultMessage="Unable to communicate with the installation" />
</Typography> </Typography>
<Typography variant="body2" style={{ color: 'black' }}> <Typography variant="body2" style={{ color: 'black' }}>
Please wait or refresh the page <FormattedMessage id="pleaseWaitOrRefresh" defaultMessage="Please wait or refresh the page" />
</Typography> </Typography>
</Container> </Container>
)} )}

View File

@ -177,14 +177,14 @@ function TreeInformation(props: TreeInformationProps) {
gutterBottom gutterBottom
sx={{ fontWeight: 'bold' }} sx={{ fontWeight: 'bold' }}
> >
Do you want to delete this folder? <FormattedMessage id="confirmDeleteFolder" defaultMessage="Do you want to delete this folder?" />
</Typography> </Typography>
<Typography <Typography
variant="body1" variant="body1"
gutterBottom gutterBottom
sx={{ fontSize: '0.875rem' }} sx={{ fontSize: '0.875rem' }}
> >
All installations of this folder will be deleted. <FormattedMessage id="deleteFolderWarning" defaultMessage="All installations of this folder will be deleted." />
</Typography> </Typography>
<div <div
@ -204,7 +204,7 @@ function TreeInformation(props: TreeInformationProps) {
}} }}
onClick={deleteFolderModalHandle} onClick={deleteFolderModalHandle}
> >
Delete <FormattedMessage id="delete" defaultMessage="Delete" />
</Button> </Button>
<Button <Button
sx={{ sx={{
@ -217,7 +217,7 @@ function TreeInformation(props: TreeInformationProps) {
}} }}
onClick={deleteFolderModalHandleCancel} onClick={deleteFolderModalHandleCancel}
> >
Cancel <FormattedMessage id="cancel" defaultMessage="Cancel" />
</Button> </Button>
</div> </div>
</Box> </Box>

View File

@ -12,6 +12,7 @@ import {
Typography, Typography,
useTheme useTheme
} from '@mui/material'; } from '@mui/material';
import { FormattedMessage } from 'react-intl';
import { InnovEnergyUser } from 'src/interfaces/UserTypes'; import { InnovEnergyUser } from 'src/interfaces/UserTypes';
import User from './User'; import User from './User';
@ -57,8 +58,8 @@ const FlatUsersView = (props: FlatUsersViewProps) => {
<TableHead> <TableHead>
<TableRow> <TableRow>
<TableCell padding="checkbox"></TableCell> <TableCell padding="checkbox"></TableCell>
<TableCell>Username</TableCell> <TableCell><FormattedMessage id="username" defaultMessage="Username" /></TableCell>
<TableCell>Email</TableCell> <TableCell><FormattedMessage id="email" defaultMessage="Email" /></TableCell>
</TableRow> </TableRow>
</TableHead> </TableHead>
<TableBody> <TableBody>

View File

@ -25,7 +25,7 @@ import axiosConfig from 'src/Resources/axiosConfig';
import { InnovEnergyUser } from 'src/interfaces/UserTypes'; import { InnovEnergyUser } from 'src/interfaces/UserTypes';
import { TokenContext } from 'src/contexts/tokenContext'; import { TokenContext } from 'src/contexts/tokenContext';
import { TabsContainerWrapper } from 'src/layouts/TabsContainerWrapper'; import { TabsContainerWrapper } from 'src/layouts/TabsContainerWrapper';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
import UserAccess from '../ManageAccess/UserAccess'; import UserAccess from '../ManageAccess/UserAccess';
interface singleUserProps { interface singleUserProps {
@ -35,6 +35,7 @@ interface singleUserProps {
function User(props: singleUserProps) { function User(props: singleUserProps) {
const theme = useTheme(); const theme = useTheme();
const intl = useIntl();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [error, setError] = useState(false); const [error, setError] = useState(false);
const [updated, setUpdated] = useState(false); const [updated, setUpdated] = useState(false);
@ -43,8 +44,8 @@ function User(props: singleUserProps) {
const tokencontext = useContext(TokenContext); const tokencontext = useContext(TokenContext);
const { removeToken } = tokencontext; const { removeToken } = tokencontext;
const tabs = [ const tabs = [
{ value: 'user', label: 'User' }, { value: 'user', label: intl.formatMessage({ id: 'user' }) },
{ value: 'manage', label: 'Access Management' } { value: 'manage', label: intl.formatMessage({ id: 'accessManagement' }) }
]; ];
const [openModalDeleteUser, setOpenModalDeleteUser] = useState(false); const [openModalDeleteUser, setOpenModalDeleteUser] = useState(false);
@ -190,7 +191,7 @@ function User(props: singleUserProps) {
gutterBottom gutterBottom
sx={{ fontWeight: 'bold' }} sx={{ fontWeight: 'bold' }}
> >
Do you want to delete this user? <FormattedMessage id="confirmDeleteUser" defaultMessage="Do you want to delete this user?" />
</Typography> </Typography>
<div <div
@ -210,7 +211,7 @@ function User(props: singleUserProps) {
}} }}
onClick={deleteUserModalHandle} onClick={deleteUserModalHandle}
> >
Delete <FormattedMessage id="delete" defaultMessage="Delete" />
</Button> </Button>
<Button <Button
sx={{ sx={{
@ -223,7 +224,7 @@ function User(props: singleUserProps) {
}} }}
onClick={deleteUserModalHandleCancel} onClick={deleteUserModalHandleCancel}
> >
Cancel <FormattedMessage id="cancel" defaultMessage="Cancel" />
</Button> </Button>
</div> </div>
</Box> </Box>
@ -274,7 +275,7 @@ function User(props: singleUserProps) {
> >
<div> <div>
<TextField <TextField
label="Name" label={intl.formatMessage({ id: 'name' })}
name="name" name="name"
value={formValues.name} value={formValues.name}
onChange={handleChange} onChange={handleChange}
@ -283,7 +284,7 @@ function User(props: singleUserProps) {
</div> </div>
<div> <div>
<TextField <TextField
label="Email" label={intl.formatMessage({ id: 'email' })}
name="email" name="email"
value={formValues.email} value={formValues.email}
onChange={handleChange} onChange={handleChange}
@ -293,7 +294,7 @@ function User(props: singleUserProps) {
</div> </div>
<div> <div>
<TextField <TextField
label="Information" label={intl.formatMessage({ id: 'information' })}
name="information" name="information"
value={formValues.information} value={formValues.information}
onChange={handleChange} onChange={handleChange}

View File

@ -13,11 +13,12 @@ import { AccessContext } from '../../../contexts/AccessContextProvider';
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
import UserForm from './userForm'; import UserForm from './userForm';
import { UserContext } from '../../../contexts/userContext'; import { UserContext } from '../../../contexts/userContext';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
import { Close as CloseIcon } from '@mui/icons-material'; import { Close as CloseIcon } from '@mui/icons-material';
import { UserType } from '../../../interfaces/UserTypes'; import { UserType } from '../../../interfaces/UserTypes';
function UsersSearch() { function UsersSearch() {
const intl = useIntl();
const [searchTerm, setSearchTerm] = useState(''); const [searchTerm, setSearchTerm] = useState('');
const { availableUsers, fetchAvailableUsers } = useContext(AccessContext); const { availableUsers, fetchAvailableUsers } = useContext(AccessContext);
const [filteredData, setFilteredData] = useState(availableUsers); const [filteredData, setFilteredData] = useState(availableUsers);
@ -147,7 +148,7 @@ function UsersSearch() {
<Grid item xs={12} md={isMobile ? 5 : 3}> <Grid item xs={12} md={isMobile ? 5 : 3}>
<FormControl variant="outlined" fullWidth> <FormControl variant="outlined" fullWidth>
<TextField <TextField
placeholder="Search" placeholder={intl.formatMessage({ id: 'search' })}
value={searchTerm} value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
fullWidth fullWidth

View File

@ -18,7 +18,7 @@ import { InnovEnergyUser } from 'src/interfaces/UserTypes';
import axiosConfig from 'src/Resources/axiosConfig'; import axiosConfig from 'src/Resources/axiosConfig';
import { TokenContext } from 'src/contexts/tokenContext'; import { TokenContext } from 'src/contexts/tokenContext';
import { I_Folder, I_Installation } from 'src/interfaces/InstallationTypes'; import { I_Folder, I_Installation } from 'src/interfaces/InstallationTypes';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
interface userFormProps { interface userFormProps {
cancel: () => void; cancel: () => void;
@ -27,10 +27,11 @@ interface userFormProps {
} }
function userForm(props: userFormProps) { function userForm(props: userFormProps) {
const intl = useIntl();
const theme = useTheme(); const theme = useTheme();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [error, setError] = useState(false); const [error, setError] = useState(false);
const [errormessage, setErrorMessage] = useState('An error has occured'); const [errormessage, setErrorMessage] = useState(intl.formatMessage({ id: 'errorOccured' }));
const [openInstallation, setOpenInstallation] = useState(false); const [openInstallation, setOpenInstallation] = useState(false);
const [openFolder, setOpenFolder] = useState(false); const [openFolder, setOpenFolder] = useState(false);
const [formValues, setFormValues] = useState<Partial<InnovEnergyUser>>({ const [formValues, setFormValues] = useState<Partial<InnovEnergyUser>>({
@ -174,7 +175,7 @@ function userForm(props: userFormProps) {
.delete(`/DeleteUser?userId=${res.data.id}`) .delete(`/DeleteUser?userId=${res.data.id}`)
.then((response) => { .then((response) => {
setLoading(false); setLoading(false);
setErrorMessage('An error has occured'); setErrorMessage(intl.formatMessage({ id: 'errorOccured' }));
setError(true); setError(true);
setTimeout(() => { setTimeout(() => {
props.cancel(); props.cancel();

View File

@ -11,6 +11,7 @@ import {
import { Helmet } from 'react-helmet-async'; import { Helmet } from 'react-helmet-async';
import RefreshTwoToneIcon from '@mui/icons-material/RefreshTwoTone'; import RefreshTwoToneIcon from '@mui/icons-material/RefreshTwoTone';
import LoadingButton from '@mui/lab/LoadingButton'; import LoadingButton from '@mui/lab/LoadingButton';
import { FormattedMessage } from 'react-intl';
const GridWrapper = styled(Grid)( const GridWrapper = styled(Grid)(
({ theme }) => ` ({ theme }) => `
@ -77,7 +78,7 @@ function Status500() {
src="/static/images/status/500.svg" src="/static/images/status/500.svg"
/> />
<Typography variant="h2" sx={{ my: 2 }}> <Typography variant="h2" sx={{ my: 2 }}>
There was an error, please try again later <FormattedMessage id="serverError" defaultMessage="There was an error, please try again later" />
</Typography> </Typography>
<Typography <Typography
variant="h4" variant="h4"
@ -85,8 +86,7 @@ function Status500() {
fontWeight="normal" fontWeight="normal"
sx={{ mb: 4 }} sx={{ mb: 4 }}
> >
The server encountered an internal error and was not able to <FormattedMessage id="serverInternalError" defaultMessage="The server encountered an internal error and was not able to complete your request" />
complete your request
</Typography> </Typography>
<LoadingButton <LoadingButton
onClick={handleClick} onClick={handleClick}
@ -95,10 +95,10 @@ function Status500() {
color="primary" color="primary"
startIcon={<RefreshTwoToneIcon />} startIcon={<RefreshTwoToneIcon />}
> >
Refresh view <FormattedMessage id="refreshView" defaultMessage="Refresh view" />
</LoadingButton> </LoadingButton>
<Button href="/overview" variant="contained" sx={{ ml: 1 }}> <Button href="/overview" variant="contained" sx={{ ml: 1 }}>
Go back <FormattedMessage id="goBack" defaultMessage="Go back" />
</Button> </Button>
</Box> </Box>
</Container> </Container>

View File

@ -404,5 +404,69 @@
"allInstallations": "Alle Installationen", "allInstallations": "Alle Installationen",
"group": "Gruppe", "group": "Gruppe",
"groups": "Gruppen", "groups": "Gruppen",
"requiredOrderNumber": "Pflichtbestellnummer" "requiredOrderNumber": "Pflichtbestellnummer",
"unableToCommunicate": "Kommunikation mit der Installation nicht möglich",
"pleaseWaitOrRefresh": "Bitte warten oder Seite aktualisieren",
"noDataForDateRange": "Keine Daten für den gewählten Zeitraum verfügbar. Bitte wählen Sie ein neueres Datum.",
"loginFailed": "Anmeldung fehlgeschlagen. Bitte versuchen Sie es erneut.",
"usernameWrong": "Benutzername ist falsch. Bitte versuchen Sie es erneut.",
"mailSentSuccessfully": "E-Mail erfolgreich gesendet.",
"passwordsDoNotMatch": "Passwörter stimmen nicht überein",
"resetPasswordFailed": "Passwort zurücksetzen fehlgeschlagen. Bitte versuchen Sie es erneut.",
"setNewPasswordFailed": "Neues Passwort setzen fehlgeschlagen. Bitte versuchen Sie es erneut.",
"successfullyAppliedConfig": "Konfigurationsdatei erfolgreich angewendet",
"configErrorOccurred": "Ein Fehler ist aufgetreten",
"confirmDeleteFolder": "Möchten Sie diesen Ordner löschen?",
"deleteFolderWarning": "Alle Installationen dieses Ordners werden gelöscht.",
"failedToLoadReport": "Bericht konnte nicht geladen werden. Stellen Sie sicher, dass die Excel-Datei in tmp_report/ abgelegt ist.",
"serverError": "Ein Fehler ist aufgetreten, bitte versuchen Sie es später erneut",
"pvViewNotAvailable": "PV-Ansicht ist derzeit nicht verfügbar",
"batteryServiceNotAvailable": "Batteriedienst ist derzeit nicht verfügbar",
"cannotChangeDateCalibration": "Sie können das Datum nicht ändern, während sich die Installation im Kalibrierungslade-Modus befindet",
"mustSpecifyFutureDate": "Sie müssen ein zukünftiges Datum angeben",
"valueBetween0And100": "Wert muss zwischen 0-100% liegen",
"pleaseProvideValidNumber": "Bitte geben Sie eine gültige Zahl ein",
"stopTimeMustBeLater": "Die Stoppzeit muss nach der Startzeit liegen",
"signIn": "Anmelden",
"username": "Benutzername",
"password": "Passwort",
"rememberMe": "Angemeldet bleiben",
"login": "Anmelden",
"close": "Schliessen",
"forgotPasswordLink": "Passwort vergessen?",
"provideYourUsername": "Geben Sie Ihren Benutzernamen ein",
"userName": "Benutzername",
"resetPassword": "Passwort zurücksetzen",
"setNewPassword": "Neues Passwort setzen",
"verifyPassword": "Passwort bestätigen",
"delete": "Löschen",
"successfullyCreatedUser": "Benutzer erfolgreich erstellt",
"serverInternalError": "Der Server hat einen internen Fehler festgestellt und konnte Ihre Anfrage nicht abschliessen",
"refreshView": "Ansicht aktualisieren",
"goBack": "Zurück",
"connectingToDevice": "Verbindung zum Gerät wird hergestellt...",
"fetchingData": "Daten werden abgerufen...",
"confirmDeleteUser": "Möchten Sie diesen Benutzer löschen?",
"accessManagement": "Zugriffsverwaltung",
"power": "Leistung",
"voltage": "Spannung",
"current": "Strom",
"battery": "Batterie",
"firmware": "Firmware",
"batteryVoltage": "Batteriespannung",
"soc": "Ladezustand",
"soh": "Gesundheitszustand",
"temperature": "Temperatur",
"warnings": "Warnungen",
"alarms": "Alarme",
"minCellVoltage": "Min. Zellenspannung",
"maxCellVoltage": "Max. Zellenspannung",
"voltageDifference": "Spannungsdifferenz",
"pv": "PV",
"showOnly": "Nur anzeigen",
"minimumSocPercent": "Minimaler Ladezustand (%)",
"powerW": "Leistung (W)",
"enterPowerValue": "Positiven oder negativen Leistungswert eingeben",
"startDateTime": "Startdatum und -zeit (Startzeit < Stoppzeit)",
"stopDateTime": "Stoppdatum und -zeit (Startzeit < Stoppzeit)"
} }

View File

@ -152,5 +152,69 @@
"demo_custom_group": "Custom (may use Mistral AI)", "demo_custom_group": "Custom (may use Mistral AI)",
"demo_custom_option": "Type custom alarm below…", "demo_custom_option": "Type custom alarm below…",
"demo_custom_placeholder": "e.g. UnknownBatteryFault", "demo_custom_placeholder": "e.g. UnknownBatteryFault",
"demo_diagnose_button": "Diagnose" "demo_diagnose_button": "Diagnose",
"unableToCommunicate": "Unable to communicate with the installation",
"pleaseWaitOrRefresh": "Please wait or refresh the page",
"noDataForDateRange": "No data available for the selected date range. Please choose a more recent date.",
"loginFailed": "Login failed. Please try again.",
"usernameWrong": "Username is wrong. Please try again.",
"mailSentSuccessfully": "Mail sent successfully.",
"passwordsDoNotMatch": "Passwords do not match",
"resetPasswordFailed": "Reset Password failed. Please try again.",
"setNewPasswordFailed": "Setting new password failed. Please try again.",
"successfullyAppliedConfig": "Successfully applied configuration file",
"configErrorOccurred": "An error has occurred",
"confirmDeleteFolder": "Do you want to delete this folder?",
"deleteFolderWarning": "All installations of this folder will be deleted.",
"failedToLoadReport": "Failed to load report. Make sure the Excel file is placed in tmp_report/",
"serverError": "There was an error, please try again later",
"pvViewNotAvailable": "Pv view is not available at the moment",
"batteryServiceNotAvailable": "Battery service is not available at the moment",
"cannotChangeDateCalibration": "You cannot change the date while the installation is in Calibration Charge Mode",
"mustSpecifyFutureDate": "You must specify a future date",
"valueBetween0And100": "Value should be between 0-100%",
"pleaseProvideValidNumber": "Please provide a valid number",
"stopTimeMustBeLater": "Stop time must be later than start time",
"signIn": "Sign in",
"username": "Username",
"password": "Password",
"rememberMe": "Remember me",
"login": "Login",
"close": "Close",
"forgotPasswordLink": "Forgot password?",
"provideYourUsername": "Provide your username",
"userName": "User Name",
"resetPassword": "Reset Password",
"setNewPassword": "Set New Password",
"verifyPassword": "Verify Password",
"delete": "Delete",
"successfullyCreatedUser": "Successfully Created User",
"serverInternalError": "The server encountered an internal error and was not able to complete your request",
"refreshView": "Refresh view",
"goBack": "Go back",
"connectingToDevice": "Connecting to the device...",
"fetchingData": "Fetching data...",
"confirmDeleteUser": "Do you want to delete this user?",
"accessManagement": "Access Management",
"power": "Power",
"voltage": "Voltage",
"current": "Current",
"battery": "Battery",
"firmware": "Firmware",
"batteryVoltage": "Battery Voltage",
"soc": "SoC",
"soh": "SoH",
"temperature": "Temperature",
"warnings": "Warnings",
"alarms": "Alarms",
"minCellVoltage": "Min Cell Voltage",
"maxCellVoltage": "Max Cell Voltage",
"voltageDifference": "Voltage Difference",
"pv": "Pv",
"showOnly": "Show Only",
"minimumSocPercent": "Minimum SoC (%)",
"powerW": "Power (W)",
"enterPowerValue": "Enter a positive or negative power value",
"startDateTime": "Start Date and Time (Start Time < Stop Time)",
"stopDateTime": "Stop Date and Time (Start Time < Stop Time)"
} }

View File

@ -404,5 +404,69 @@
"groupTabs": "Groupes", "groupTabs": "Groupes",
"groupTree": "Arborescence de groupes", "groupTree": "Arborescence de groupes",
"installationTabs": "Installations", "installationTabs": "Installations",
"navigationTabs": "Navigation" "navigationTabs": "Navigation",
"unableToCommunicate": "Impossible de communiquer avec l'installation",
"pleaseWaitOrRefresh": "Veuillez patienter ou actualiser la page",
"noDataForDateRange": "Aucune donnée disponible pour la période sélectionnée. Veuillez choisir une date plus récente.",
"loginFailed": "Échec de la connexion. Veuillez réessayer.",
"usernameWrong": "Nom d'utilisateur incorrect. Veuillez réessayer.",
"mailSentSuccessfully": "E-mail envoyé avec succès.",
"passwordsDoNotMatch": "Les mots de passe ne correspondent pas",
"resetPasswordFailed": "La réinitialisation du mot de passe a échoué. Veuillez réessayer.",
"setNewPasswordFailed": "La définition du nouveau mot de passe a échoué. Veuillez réessayer.",
"successfullyAppliedConfig": "Fichier de configuration appliqué avec succès",
"configErrorOccurred": "Une erreur s'est produite",
"confirmDeleteFolder": "Voulez-vous supprimer ce dossier ?",
"deleteFolderWarning": "Toutes les installations de ce dossier seront supprimées.",
"failedToLoadReport": "Impossible de charger le rapport. Assurez-vous que le fichier Excel est placé dans tmp_report/",
"serverError": "Une erreur s'est produite, veuillez réessayer plus tard",
"pvViewNotAvailable": "La vue PV n'est pas disponible pour le moment",
"batteryServiceNotAvailable": "Le service batterie n'est pas disponible pour le moment",
"cannotChangeDateCalibration": "Vous ne pouvez pas changer la date pendant que l'installation est en mode de charge de calibration",
"mustSpecifyFutureDate": "Vous devez spécifier une date future",
"valueBetween0And100": "La valeur doit être entre 0-100%",
"pleaseProvideValidNumber": "Veuillez fournir un nombre valide",
"stopTimeMustBeLater": "L'heure d'arrêt doit être postérieure à l'heure de début",
"signIn": "Se connecter",
"username": "Nom d'utilisateur",
"password": "Mot de passe",
"rememberMe": "Se souvenir de moi",
"login": "Connexion",
"close": "Fermer",
"forgotPasswordLink": "Mot de passe oublié ?",
"provideYourUsername": "Entrez votre nom d'utilisateur",
"userName": "Nom d'utilisateur",
"resetPassword": "Réinitialiser le mot de passe",
"setNewPassword": "Définir un nouveau mot de passe",
"verifyPassword": "Vérifier le mot de passe",
"delete": "Supprimer",
"successfullyCreatedUser": "Utilisateur créé avec succès",
"serverInternalError": "Le serveur a rencontré une erreur interne et n'a pas pu traiter votre demande",
"refreshView": "Actualiser la vue",
"goBack": "Retour",
"connectingToDevice": "Connexion à l'appareil en cours...",
"fetchingData": "Récupération des données...",
"confirmDeleteUser": "Voulez-vous supprimer cet utilisateur ?",
"accessManagement": "Gestion des accès",
"power": "Puissance",
"voltage": "Tension",
"current": "Courant",
"battery": "Batterie",
"firmware": "Firmware",
"batteryVoltage": "Tension de la batterie",
"soc": "État de charge",
"soh": "État de santé",
"temperature": "Température",
"warnings": "Avertissements",
"alarms": "Alarmes",
"minCellVoltage": "Tension min. cellule",
"maxCellVoltage": "Tension max. cellule",
"voltageDifference": "Différence de tension",
"pv": "PV",
"showOnly": "Afficher uniquement",
"minimumSocPercent": "SoC minimum (%)",
"powerW": "Puissance (W)",
"enterPowerValue": "Entrez une valeur de puissance positive ou négative",
"startDateTime": "Date et heure de début (Début < Fin)",
"stopDateTime": "Date et heure de fin (Début < Fin)"
} }

View File

@ -404,5 +404,69 @@
"alarm_AFCIFault": "Guasto AFCI", "alarm_AFCIFault": "Guasto AFCI",
"alarm_GFCIHigh": "Corrente di guasto a terra elevata", "alarm_GFCIHigh": "Corrente di guasto a terra elevata",
"alarm_PVVoltageHigh": "Tensione PV elevata", "alarm_PVVoltageHigh": "Tensione PV elevata",
"alarm_OffGridBusVoltageTooLow": "Tensione Bus Fuori Rete Troppo Bassa" "alarm_OffGridBusVoltageTooLow": "Tensione Bus Fuori Rete Troppo Bassa",
"unableToCommunicate": "Impossibile comunicare con l'installazione",
"pleaseWaitOrRefresh": "Attendere o aggiornare la pagina",
"noDataForDateRange": "Nessun dato disponibile per il periodo selezionato. Scegliere una data più recente.",
"loginFailed": "Accesso fallito. Riprovare.",
"usernameWrong": "Nome utente errato. Riprovare.",
"mailSentSuccessfully": "E-mail inviata con successo.",
"passwordsDoNotMatch": "Le password non corrispondono",
"resetPasswordFailed": "Reimpostazione password fallita. Riprovare.",
"setNewPasswordFailed": "Impostazione nuova password fallita. Riprovare.",
"successfullyAppliedConfig": "File di configurazione applicato con successo",
"configErrorOccurred": "Si è verificato un errore",
"confirmDeleteFolder": "Vuoi eliminare questa cartella?",
"deleteFolderWarning": "Tutte le installazioni di questa cartella verranno eliminate.",
"failedToLoadReport": "Impossibile caricare il rapporto. Assicurarsi che il file Excel sia in tmp_report/",
"serverError": "Si è verificato un errore, riprovare più tardi",
"pvViewNotAvailable": "La vista PV non è disponibile al momento",
"batteryServiceNotAvailable": "Il servizio batteria non è disponibile al momento",
"cannotChangeDateCalibration": "Non è possibile cambiare la data mentre l'installazione è in modalità di carica di calibrazione",
"mustSpecifyFutureDate": "Specificare una data futura",
"valueBetween0And100": "Il valore deve essere tra 0-100%",
"pleaseProvideValidNumber": "Inserire un numero valido",
"stopTimeMustBeLater": "L'ora di fine deve essere successiva all'ora di inizio",
"signIn": "Accedi",
"username": "Nome utente",
"password": "Password",
"rememberMe": "Ricordami",
"login": "Accedi",
"close": "Chiudi",
"forgotPasswordLink": "Password dimenticata?",
"provideYourUsername": "Inserisci il tuo nome utente",
"userName": "Nome utente",
"resetPassword": "Reimposta password",
"setNewPassword": "Imposta nuova password",
"verifyPassword": "Verifica password",
"delete": "Elimina",
"successfullyCreatedUser": "Utente creato con successo",
"serverInternalError": "Il server ha riscontrato un errore interno e non è stato in grado di completare la richiesta",
"refreshView": "Aggiorna vista",
"goBack": "Indietro",
"connectingToDevice": "Connessione al dispositivo in corso...",
"fetchingData": "Recupero dati in corso...",
"confirmDeleteUser": "Vuoi eliminare questo utente?",
"accessManagement": "Gestione accessi",
"power": "Potenza",
"voltage": "Tensione",
"current": "Corrente",
"battery": "Batteria",
"firmware": "Firmware",
"batteryVoltage": "Tensione batteria",
"soc": "Stato di carica",
"soh": "Stato di salute",
"temperature": "Temperatura",
"warnings": "Avvisi",
"alarms": "Allarmi",
"minCellVoltage": "Tensione min. cella",
"maxCellVoltage": "Tensione max. cella",
"voltageDifference": "Differenza di tensione",
"pv": "PV",
"showOnly": "Mostra solo",
"minimumSocPercent": "SoC minimo (%)",
"powerW": "Potenza (W)",
"enterPowerValue": "Inserire un valore di potenza positivo o negativo",
"startDateTime": "Data e ora di inizio (Inizio < Fine)",
"stopDateTime": "Data e ora di fine (Inizio < Fine)"
} }