feat: Added support for i18n (#2439)
* Added translation for various react components in OHIF-v3 * Added a test language for debugging- test-LNG * Added copy for test language to not get overwritten
This commit is contained in:
1 parent
fdb6ca41d6
commit
1bf651e763
42 files changed
+365
-63
No files matched your search
@@ -7,7 +7,7 @@ import { useHistory } from 'react-router-dom';
|
||||
import { NavBar, Svg, Icon, IconButton, Dropdown } from '@ohif/ui';
|
||||
|
||||
function Header({ children, menuOptions, isReturnEnabled, isSticky, WhiteLabeling }) {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useTranslation('Header');
|
||||
const history = useHistory();
|
||||
|
||||
// TODO: this should be passed in as a prop instead and the react-router-dom
|
||||
@@ -39,7 +39,7 @@ function Header({ children, menuOptions, isReturnEnabled, isSticky, WhiteLabelin
|
||||
<div className="flex items-center">{children}</div>
|
||||
<div className="flex items-center">
|
||||
<span className="mr-3 text-lg text-common-light">
|
||||
{t('Header:INVESTIGATIONAL USE ONLY')}
|
||||
{t('INVESTIGATIONAL USE ONLY')}
|
||||
</span>
|
||||
<Dropdown id="options" showDropdownIcon={false} list={menuOptions}>
|
||||
<IconButton
|
||||
|
||||
@@ -2,12 +2,16 @@ import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { HotkeyField, Typography } from '@ohif/ui';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
|
||||
/* TODO: Move these configs and utils to core? */
|
||||
import { MODIFIER_KEYS } from './hotkeysConfig';
|
||||
import { validate, splitHotkeyDefinitionsAndCreateTuples } from './utils';
|
||||
|
||||
const HotkeysPreferences = ({ disabled, hotkeyDefinitions, errors: controlledErrors, onChange }) => {
|
||||
const { t } = useTranslation('UserPreferencesModal');
|
||||
|
||||
const visibleHotkeys = Object.keys(hotkeyDefinitions)
|
||||
.filter(key => hotkeyDefinitions[key].isEditable)
|
||||
.reduce((obj, key) => {
|
||||
@@ -57,7 +61,7 @@ const HotkeysPreferences = ({ disabled, hotkeyDefinitions, errors: controlledErr
|
||||
variant='subtitle'
|
||||
className={classNames('pr-6 w-full text-right text-primary-light', !isFirst && 'hidden')}
|
||||
>
|
||||
Function
|
||||
{t('Function')}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant='subtitle'
|
||||
@@ -70,7 +74,7 @@ const HotkeysPreferences = ({ disabled, hotkeyDefinitions, errors: controlledErr
|
||||
variant='subtitle'
|
||||
className={classNames('pr-6 pl-0 text-left text-primary-light', !isFirst && 'hidden')}
|
||||
>
|
||||
Shortcut
|
||||
{t('Shortcut')}
|
||||
</Typography>
|
||||
<div className={classNames('flex flex-col w-32', isFirst && 'mt-5')}>
|
||||
<HotkeyField
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Icon } from '../';
|
||||
|
||||
@@ -21,6 +22,8 @@ const InputLabelWrapper = ({
|
||||
className,
|
||||
children,
|
||||
}) => {
|
||||
const { t } = useTranslation("StudyList")
|
||||
|
||||
const onClickHandler = e => {
|
||||
if (!isSortable) {
|
||||
return;
|
||||
@@ -38,7 +41,7 @@ const InputLabelWrapper = ({
|
||||
onKeyDown={onClickHandler}
|
||||
tabIndex="0"
|
||||
>
|
||||
{label}
|
||||
{t(label)}
|
||||
{isSortable && (
|
||||
<Icon
|
||||
name={sortIconMap[sortDirection]}
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import MeasurementItem from './MeasurementItem';
|
||||
|
||||
const MeasurementTable = ({ data, title, amount, onClick, onEdit }) => {
|
||||
const { t } = useTranslation("MeasurementTable")
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between px-2 py-1 bg-secondary-main">
|
||||
<span className="text-base font-bold tracking-widest text-white uppercase">
|
||||
{title}
|
||||
{t(title)}
|
||||
</span>
|
||||
<span className="text-base font-bold text-white">{amount}</span>
|
||||
</div>
|
||||
@@ -31,7 +34,7 @@ const MeasurementTable = ({ data, title, amount, onClick, onEdit }) => {
|
||||
<div className="w-6 py-1 text-base text-center transition duration-300 bg-primary-dark text-primary-light group-hover:bg-secondary-main"></div>
|
||||
<div className="flex items-center justify-between flex-1 px-2 py-4">
|
||||
<span className="flex items-center flex-1 mb-1 text-base text-primary-light">
|
||||
No tracked measurements
|
||||
{t('No tracked measurements')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Button, Icon } from '../';
|
||||
|
||||
@@ -69,6 +70,8 @@ const SidePanel = ({
|
||||
defaultComponentOpen,
|
||||
childComponents,
|
||||
}) => {
|
||||
const { t } = useTranslation('SidePanel');
|
||||
|
||||
const [componentOpen, setComponentOpen] = useState(defaultComponentOpen);
|
||||
|
||||
const openStatus = componentOpen ? 'open' : 'closed';
|
||||
@@ -101,7 +104,7 @@ const SidePanel = ({
|
||||
className="text-primary-active"
|
||||
/>
|
||||
<span className="mt-2 text-white text-xs">
|
||||
{childComponent.iconLabel}
|
||||
{t(childComponent.iconLabel)}
|
||||
</span>
|
||||
</Button>
|
||||
);
|
||||
@@ -139,7 +142,7 @@ const SidePanel = ({
|
||||
style={{ ...position[side] }}
|
||||
/>
|
||||
<span className="flex-1 text-primary-active">
|
||||
{childComponent.label}
|
||||
{t(childComponent.label)}
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import OutsideClickHandler from 'react-outside-click-handler';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Icon, Tooltip, ListMenu } from '@ohif/ui';
|
||||
|
||||
@@ -83,6 +84,8 @@ const SplitButton = ({
|
||||
renderer,
|
||||
onInteraction,
|
||||
}) => {
|
||||
const { t } = useTranslation('Buttons');
|
||||
|
||||
const { primaryToolId, toggles } = bState;
|
||||
/* Bubbles up individual item clicks */
|
||||
const getSplitButtonItems = items =>
|
||||
@@ -221,14 +224,14 @@ const SplitButton = ({
|
||||
className={classes.Content({ ...state })}
|
||||
data-cy={`${groupId}-list-menu`}
|
||||
>
|
||||
<ListMenu items={state.items} renderer={renderer} />
|
||||
<ListMenu items={state.items} renderer={(args) => renderer({ ...args, t })} />
|
||||
</div>
|
||||
</div>
|
||||
</OutsideClickHandler>
|
||||
);
|
||||
};
|
||||
|
||||
const DefaultListItemRenderer = ({ icon, label, isActive }) => (
|
||||
const DefaultListItemRenderer = ({ icon, label, isActive, t }) => (
|
||||
<div
|
||||
className={classNames(
|
||||
'flex flex-row items-center p-3 h-8 w-full hover:bg-primary-dark',
|
||||
@@ -239,7 +242,7 @@ const DefaultListItemRenderer = ({ icon, label, isActive }) => (
|
||||
<Icon name={icon} className="w-5 h-5 text-common-bright" />
|
||||
</span>
|
||||
<span className="mr-5 text-base whitespace-pre text-common-bright">
|
||||
{label}
|
||||
{t(label)}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { ButtonGroup, Button, StudyItem, ThumbnailList } from '../';
|
||||
|
||||
@@ -29,6 +30,8 @@ const StudyBrowser = ({
|
||||
onClickUntrack,
|
||||
activeDisplaySetInstanceUID,
|
||||
}) => {
|
||||
const { t } = useTranslation("StudyBrowser")
|
||||
|
||||
const getTabContent = () => {
|
||||
const tabData = tabs.find(tab => tab.name === activeTabName);
|
||||
|
||||
@@ -96,7 +99,7 @@ const StudyBrowser = ({
|
||||
}}
|
||||
disabled={isDisabled}
|
||||
>
|
||||
{label}
|
||||
{t(label)}
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Table, TableHead, TableBody, TableRow, TableCell } from '../';
|
||||
|
||||
@@ -8,6 +9,9 @@ const StudyListExpandedRow = ({
|
||||
seriesTableDataSource,
|
||||
children,
|
||||
}) => {
|
||||
const { t } = useTranslation('StudyList');
|
||||
|
||||
|
||||
return (
|
||||
<div className="w-full bg-black py-4 pl-12 pr-2">
|
||||
<div className="block">{children}</div>
|
||||
@@ -18,7 +22,7 @@ const StudyListExpandedRow = ({
|
||||
{Object.keys(seriesTableColumns).map(columnKey => {
|
||||
return (
|
||||
<TableCell key={columnKey}>
|
||||
{seriesTableColumns[columnKey]}
|
||||
{t(seriesTableColumns[columnKey])}
|
||||
</TableCell>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Button, Icon, Typography, InputGroup } from '../../components';
|
||||
|
||||
@@ -11,6 +12,7 @@ const StudyListFilter = ({
|
||||
isFiltering,
|
||||
numOfStudies,
|
||||
}) => {
|
||||
const { t } = useTranslation("StudyList")
|
||||
const { sortBy, sortDirection } = filterValues;
|
||||
const filterSorting = { sortBy, sortDirection };
|
||||
const setFilterSorting = sortingValues => {
|
||||
@@ -29,7 +31,7 @@ const StudyListFilter = ({
|
||||
<div className="flex flex-row justify-between px-12 mb-5">
|
||||
<div className="flex flex-row">
|
||||
<Typography variant="h4" className="mr-6 text-primary-light">
|
||||
Study list
|
||||
{t('Study list')}
|
||||
</Typography>
|
||||
</div>
|
||||
<div className="flex flex-row">
|
||||
@@ -42,7 +44,7 @@ const StudyListFilter = ({
|
||||
startIcon={<Icon name="cancel" />}
|
||||
onClick={clearFilters}
|
||||
>
|
||||
Clear filters
|
||||
{t('Clear filters')}
|
||||
</Button>
|
||||
)}
|
||||
<Typography variant="h4" className="mr-2" data-cy={"num-studies"}>
|
||||
@@ -52,7 +54,7 @@ const StudyListFilter = ({
|
||||
variant="h6"
|
||||
className="self-end pb-1 text-common-light"
|
||||
>
|
||||
Studies
|
||||
{t('Studies')}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
@@ -77,7 +79,7 @@ const StudyListFilter = ({
|
||||
<div className="container m-auto">
|
||||
<div className="py-1 text-base text-center rounded-b bg-primary-main">
|
||||
<p className="text-white">
|
||||
Filter list to 100 studies or less to enable sorting
|
||||
{t('Filter list to 100 studies or less to enable sorting')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, ButtonGroup, Typography, Select } from '../';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const StudyListPagination = ({
|
||||
onChangePage,
|
||||
@@ -8,6 +9,8 @@ const StudyListPagination = ({
|
||||
perPage,
|
||||
onChangePerPage,
|
||||
}) => {
|
||||
const { t } = useTranslation("StudyList")
|
||||
|
||||
const navigateToPage = page => {
|
||||
const toPage = page < 1 ? 1 : page;
|
||||
onChangePage(toPage);
|
||||
@@ -42,7 +45,7 @@ const StudyListPagination = ({
|
||||
onChange={onSelectedRange}
|
||||
/>
|
||||
<Typography className="text-base opacity-60">
|
||||
Results per page
|
||||
{t('Results per page')}
|
||||
</Typography>
|
||||
</div>
|
||||
<div className="">
|
||||
@@ -64,14 +67,14 @@ const StudyListPagination = ({
|
||||
className="border-primary-main py-2 px-2 text-base"
|
||||
color="white"
|
||||
onClick={() => navigateToPage(currentPage - 1)}
|
||||
>{`< Previous`}</Button>
|
||||
>{t(`< Previous`)}</Button>
|
||||
<Button
|
||||
size="initial"
|
||||
className="border-primary-main py-2 px-4 text-base"
|
||||
color="white"
|
||||
onClick={() => navigateToPage(currentPage + 1)}
|
||||
>
|
||||
{`Next >`}
|
||||
{t(`Next >`)}
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import './tooltip.css';
|
||||
|
||||
@@ -33,6 +34,7 @@ const Tooltip = ({
|
||||
isDisabled,
|
||||
}) => {
|
||||
const [isActive, setIsActive] = useState(false);
|
||||
const { t } = useTranslation('Buttons');
|
||||
|
||||
const handleMouseOver = () => {
|
||||
if (!isActive) {
|
||||
@@ -72,7 +74,7 @@ const Tooltip = ({
|
||||
}
|
||||
)}
|
||||
>
|
||||
{content}
|
||||
{typeof content === 'string' ? t(content) : content}
|
||||
<svg
|
||||
className="absolute h-4 text-primary-dark stroke-secondary-main"
|
||||
style={arrowPositionStyle[position]}
|
||||
|
||||
@@ -66,10 +66,10 @@ const UserPreferences = ({ availableLanguages, defaultLanguage, currentLanguage,
|
||||
|
||||
return (
|
||||
<div className="p-2">
|
||||
<Section title="General">
|
||||
<Section title={t('General')}>
|
||||
<div className="flex flex-row justify-center items-center w-72">
|
||||
<Typography variant="subtitle" className="mr-5 text-right h-full">
|
||||
Language
|
||||
{t('Language')}
|
||||
</Typography>
|
||||
<Select
|
||||
isClearable={false}
|
||||
@@ -79,7 +79,7 @@ const UserPreferences = ({ availableLanguages, defaultLanguage, currentLanguage,
|
||||
/>
|
||||
</div>
|
||||
</Section>
|
||||
<Section title="Hotkeys">
|
||||
<Section title={t('Hotkeys')}>
|
||||
<HotkeysPreferences
|
||||
disabled={disabled}
|
||||
hotkeyDefinitions={state.hotkeyDefinitions}
|
||||
@@ -135,7 +135,7 @@ UserPreferences.defaultProps = {
|
||||
onCancel: noop,
|
||||
onSubmit: noop,
|
||||
onReset: noop,
|
||||
disabled: true
|
||||
disabled: false
|
||||
};
|
||||
|
||||
export default UserPreferences;
|
||||
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { Icon, ButtonGroup, Button, Tooltip, CinePlayer } from '../';
|
||||
import useOnClickOutside from '../../utils/useOnClickOutside';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const classes = {
|
||||
infoHeader: 'text-base text-primary-light',
|
||||
@@ -369,6 +370,8 @@ function PatientInfo({
|
||||
isOpen,
|
||||
showPatientInfoRef,
|
||||
}) {
|
||||
const { t } = useTranslation("PatientInfo")
|
||||
|
||||
while (patientAge.charAt(0) === '0') {
|
||||
patientAge = patientAge.substr(1);
|
||||
}
|
||||
@@ -394,7 +397,7 @@ function PatientInfo({
|
||||
</span>
|
||||
<div className="flex pb-4 mt-4 mb-4 border-b border-secondary-main">
|
||||
<div className={classnames(classes.firstRow)}>
|
||||
<span className={classnames(classes.infoHeader)}>Sex</span>
|
||||
<span className={classnames(classes.infoHeader)}>{t('Sex')}</span>
|
||||
<span
|
||||
className={classnames(classes.infoText)}
|
||||
title={patientSex}
|
||||
@@ -403,7 +406,7 @@ function PatientInfo({
|
||||
</span>
|
||||
</div>
|
||||
<div className={classnames(classes.row)}>
|
||||
<span className={classnames(classes.infoHeader)}>Age</span>
|
||||
<span className={classnames(classes.infoHeader)}>{t('Age')}</span>
|
||||
<span
|
||||
className={classnames(classes.infoText)}
|
||||
title={patientAge}
|
||||
@@ -412,7 +415,7 @@ function PatientInfo({
|
||||
</span>
|
||||
</div>
|
||||
<div className={classnames(classes.row)}>
|
||||
<span className={classnames(classes.infoHeader)}>MRN</span>
|
||||
<span className={classnames(classes.infoHeader)}>{t('MRN')}</span>
|
||||
<span className={classnames(classes.infoText)} title={MRN}>
|
||||
{MRN}
|
||||
</span>
|
||||
@@ -421,7 +424,7 @@ function PatientInfo({
|
||||
<div className="flex">
|
||||
<div className={classnames(classes.firstRow)}>
|
||||
<span className={classnames(classes.infoHeader)}>
|
||||
Thickness
|
||||
{t('Thickness')}
|
||||
</span>
|
||||
<span
|
||||
className={classnames(classes.infoText)}
|
||||
@@ -432,7 +435,7 @@ function PatientInfo({
|
||||
</div>
|
||||
<div className={classnames(classes.row)}>
|
||||
<span className={classnames(classes.infoHeader)}>
|
||||
Spacing
|
||||
{t('Spacing')}
|
||||
</span>
|
||||
<span
|
||||
className={classnames(classes.infoText)}
|
||||
@@ -443,7 +446,7 @@ function PatientInfo({
|
||||
</div>
|
||||
<div className={classnames(classes.row)}>
|
||||
<span className={classnames(classes.infoHeader)}>
|
||||
Scanner
|
||||
{t('Scanner')}
|
||||
</span>
|
||||
<span
|
||||
className={classnames(classes.infoText)}
|
||||
|
||||
@@ -5,6 +5,7 @@ import React, {
|
||||
createRef,
|
||||
useRef,
|
||||
} from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import classnames from 'classnames';
|
||||
|
||||
@@ -47,6 +48,8 @@ const ViewportDownloadForm = ({
|
||||
maximumSize,
|
||||
canvasClass,
|
||||
}) => {
|
||||
const { t } = useTranslation('Modals');
|
||||
|
||||
const [filename, setFilename] = useState(DEFAULT_FILENAME);
|
||||
const [fileType, setFileType] = useState(['jpg']);
|
||||
|
||||
@@ -272,8 +275,7 @@ const ViewportDownloadForm = ({
|
||||
return (
|
||||
<div>
|
||||
<Typography variant="h6">
|
||||
Please specify the dimensions, filename, and desired type for the output
|
||||
image.
|
||||
{t('Please specify the dimensions, filename, and desired type for the output image.')}
|
||||
</Typography>
|
||||
|
||||
<div className="flex flex-col mt-6">
|
||||
@@ -282,7 +284,7 @@ const ViewportDownloadForm = ({
|
||||
data-cy="file-name"
|
||||
value={filename}
|
||||
onChange={evt => setFilename(evt.target.value)}
|
||||
label="File Name"
|
||||
label={t("File Name")}
|
||||
/>
|
||||
{renderErrorHandler('filename')}
|
||||
</div>
|
||||
@@ -294,7 +296,7 @@ const ViewportDownloadForm = ({
|
||||
type="number"
|
||||
min={minimumSize}
|
||||
max={maximumSize}
|
||||
label="Image width (px)"
|
||||
label={t("Image width (px)")}
|
||||
value={dimensions.width}
|
||||
onChange={evt => onDimensionsChange(evt.target.value, 'width')}
|
||||
data-cy="image-width"
|
||||
@@ -306,7 +308,7 @@ const ViewportDownloadForm = ({
|
||||
type="number"
|
||||
min={minimumSize}
|
||||
max={maximumSize}
|
||||
label="Image height (px)"
|
||||
label={t("Image height (px)")}
|
||||
value={dimensions.height}
|
||||
onChange={evt => onDimensionsChange(evt.target.value, 'height')}
|
||||
data-cy="image-height"
|
||||
@@ -335,7 +337,7 @@ const ViewportDownloadForm = ({
|
||||
<div>
|
||||
<InputLabelWrapper
|
||||
sortDirection="none"
|
||||
label="File Type"
|
||||
label={t("File Type")}
|
||||
isSortable={false}
|
||||
onLabelClick={() => {}}
|
||||
>
|
||||
@@ -363,7 +365,7 @@ const ViewportDownloadForm = ({
|
||||
checked={showAnnotations}
|
||||
onChange={event => setShowAnnotations(event.target.checked)}
|
||||
/>
|
||||
<Typography>Show Annotations</Typography>
|
||||
<Typography>{t("Show Annotations")}</Typography>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -375,7 +377,7 @@ const ViewportDownloadForm = ({
|
||||
className="p-4 rounded bg-secondary-dark border-secondary-primary"
|
||||
data-cy="image-preview"
|
||||
>
|
||||
<Typography variant="h5">Image preview</Typography>
|
||||
<Typography variant="h5">{t("Image preview")}</Typography>
|
||||
{activeViewport && (<div
|
||||
className="mx-auto my-0"
|
||||
style={{
|
||||
@@ -397,7 +399,7 @@ const ViewportDownloadForm = ({
|
||||
</div>)}
|
||||
{!activeViewport &&
|
||||
<Typography className="mt-4">
|
||||
Active viewport has no displayed image
|
||||
{t("Active viewport has no displayed image")}
|
||||
</Typography>
|
||||
}
|
||||
</div>
|
||||
@@ -405,7 +407,7 @@ const ViewportDownloadForm = ({
|
||||
|
||||
<div className="flex justify-end mt-4">
|
||||
<Button data-cy="cancel-btn" variant="outlined" onClick={onClose}>
|
||||
Cancel
|
||||
{t("Cancel")}
|
||||
</Button>
|
||||
<Button
|
||||
className="ml-2"
|
||||
@@ -414,7 +416,7 @@ const ViewportDownloadForm = ({
|
||||
color="primary"
|
||||
data-cy="download-btn"
|
||||
>
|
||||
Download
|
||||
{t("Download")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,6 +7,7 @@ import React, {
|
||||
} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const ModalContext = createContext(null);
|
||||
const { Provider } = ModalContext;
|
||||
@@ -36,6 +37,8 @@ const ModalProvider = ({ children, modal: Modal, service }) => {
|
||||
title: null,
|
||||
customClassName: '',
|
||||
};
|
||||
const { t } = useTranslation('Modals');
|
||||
|
||||
|
||||
const [options, setOptions] = useState(DEFAULT_OPTIONS);
|
||||
|
||||
@@ -86,7 +89,7 @@ const ModalProvider = ({ children, modal: Modal, service }) => {
|
||||
className={classNames(customClassName, ModalContent.className)}
|
||||
shouldCloseOnEsc={shouldCloseOnEsc}
|
||||
isOpen={isOpen}
|
||||
title={title}
|
||||
title={t(title)}
|
||||
closeButton={closeButton}
|
||||
onClose={hide}
|
||||
>
|
||||
|
||||
Reference in new issue
Block a user