From d14a8f0199db95cd9e85866a011b64d6bf830d57 Mon Sep 17 00:00:00 2001 From: Pavel Date: Mon, 11 Dec 2023 19:43:58 +0500 Subject: [PATCH] feat(i18n): enhanced i18n support (#3761) --- extensions/default/src/getPanelModule.tsx | 7 ++-- .../promptBeginTracking.js | 9 +++-- .../promptTrackNewStudy.js | 10 +++-- .../src/getPanelModule.tsx | 5 ++- .../viewports/TrackedCornerstoneViewport.tsx | 13 +++--- modes/basic-dev-mode/src/index.js | 3 +- modes/basic-test-mode/src/index.ts | 3 +- modes/longitudinal/src/index.js | 3 +- modes/microscopy/src/index.tsx | 3 +- modes/segmentation/src/index.tsx | 3 +- modes/tmtv/src/index.js | 3 +- platform/app/src/routes/WorkList/WorkList.tsx | 2 +- platform/core/src/utils/formatDate.js | 3 +- platform/i18n/src/locales/en-US/Common.json | 5 ++- .../i18n/src/locales/en-US/ErrorBoundary.json | 8 ++++ .../src/locales/en-US/HotkeysValidators.json | 6 +++ .../src/locales/en-US/MeasurementTable.json | 4 +- platform/i18n/src/locales/en-US/Messages.json | 1 + platform/i18n/src/locales/en-US/Modes.json | 8 ++++ .../src/locales/en-US/SegmentationTable.json | 18 +++++++++ .../i18n/src/locales/en-US/StudyItem.json | 3 ++ .../i18n/src/locales/en-US/StudyList.json | 14 ++++--- .../src/locales/en-US/ThumbnailTracked.json | 5 +++ .../src/locales/en-US/TooltipClipboard.json | 4 ++ .../en-US/TrackedCornerstoneViewport.json | 6 +++ platform/i18n/src/locales/en-US/index.js | 16 ++++++++ platform/i18n/src/locales/es/StudyList.json | 2 +- .../i18n/src/locales/test-LNG/Common.json | 5 ++- .../src/locales/test-LNG/ErrorBoundary.json | 8 ++++ .../locales/test-LNG/HotkeysValidators.json | 6 +++ .../locales/test-LNG/MeasurementTable.json | 4 +- .../i18n/src/locales/test-LNG/Messages.json | 16 ++++++++ platform/i18n/src/locales/test-LNG/Modes.json | 7 +++- .../locales/test-LNG/SegmentationTable.json | 18 +++++++++ .../i18n/src/locales/test-LNG/StudyItem.json | 3 ++ .../i18n/src/locales/test-LNG/StudyList.json | 16 ++++---- .../locales/test-LNG/ThumbnailTracked.json | 5 +++ .../locales/test-LNG/TooltipClipboard.json | 4 ++ .../test-LNG/TrackedCornerstoneViewport.json | 6 +++ platform/i18n/src/locales/test-LNG/index.js | 40 +++++++++++++------ platform/i18n/src/locales/zh/StudyList.json | 8 ++-- .../DisplaySetMessageListTooltip.tsx | 2 +- .../components/EmptyStudies/EmptyStudies.tsx | 4 +- .../ErrorBoundary/ErrorBoundary.tsx | 15 ++++--- .../HotkeysPreferences/hotkeysValidators.js | 9 +++-- .../SegmentationGroupTable/AddSegmentRow.tsx | 4 +- .../NoSegmentationRow.tsx | 4 +- .../SegmentationConfig.tsx | 20 ++++++---- .../SegmentationDropDownRow.tsx | 14 ++++--- .../SegmentationGroupTable.tsx | 4 +- .../ui/src/components/SidePanel/SidePanel.tsx | 3 -- .../ui/src/components/StudyItem/StudyItem.tsx | 4 +- .../StudyListFilter/StudyListFilter.tsx | 14 +++---- .../ThumbnailTracked/ThumbnailTracked.tsx | 14 +++---- .../TooltipClipboard/TooltipClipboard.tsx | 7 +++- 55 files changed, 318 insertions(+), 113 deletions(-) create mode 100644 platform/i18n/src/locales/en-US/ErrorBoundary.json create mode 100644 platform/i18n/src/locales/en-US/HotkeysValidators.json create mode 100644 platform/i18n/src/locales/en-US/Modes.json create mode 100644 platform/i18n/src/locales/en-US/SegmentationTable.json create mode 100644 platform/i18n/src/locales/en-US/StudyItem.json create mode 100644 platform/i18n/src/locales/en-US/ThumbnailTracked.json create mode 100644 platform/i18n/src/locales/en-US/TooltipClipboard.json create mode 100644 platform/i18n/src/locales/en-US/TrackedCornerstoneViewport.json create mode 100644 platform/i18n/src/locales/test-LNG/ErrorBoundary.json create mode 100644 platform/i18n/src/locales/test-LNG/HotkeysValidators.json create mode 100644 platform/i18n/src/locales/test-LNG/Messages.json create mode 100644 platform/i18n/src/locales/test-LNG/SegmentationTable.json create mode 100644 platform/i18n/src/locales/test-LNG/StudyItem.json create mode 100644 platform/i18n/src/locales/test-LNG/ThumbnailTracked.json create mode 100644 platform/i18n/src/locales/test-LNG/TooltipClipboard.json create mode 100644 platform/i18n/src/locales/test-LNG/TrackedCornerstoneViewport.json diff --git a/extensions/default/src/getPanelModule.tsx b/extensions/default/src/getPanelModule.tsx index 559f98fcad7..e294805dfbd 100644 --- a/extensions/default/src/getPanelModule.tsx +++ b/extensions/default/src/getPanelModule.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { WrappedPanelStudyBrowser, PanelMeasurementTable } from './Panels'; +import i18n from 'i18next'; // TODO: // - No loading UI exists yet @@ -22,7 +23,7 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager }) name: 'seriesList', iconName: 'tab-studies', iconLabel: 'Studies', - label: 'Studies', + label: i18n.t('SidePanel:Studies'), component: WrappedPanelStudyBrowser.bind(null, { commandsManager, extensionManager, @@ -33,8 +34,8 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager }) name: 'measure', iconName: 'tab-linear', iconLabel: 'Measure', - label: 'Measurements', - secondaryLabel: 'Measurements', + label: i18n.t('SidePanel:Measurements'), + secondaryLabel: i18n.t('SidePanel:Measurements'), component: wrappedMeasurementPanel, }, ]; diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptBeginTracking.js b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptBeginTracking.js index 75182383645..41fa0baca8e 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptBeginTracking.js +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptBeginTracking.js @@ -1,4 +1,5 @@ import { ButtonEnums } from '@ohif/ui'; +import i18n from 'i18next'; const RESPONSE = { NO_NEVER: -1, @@ -26,24 +27,24 @@ function promptBeginTracking({ servicesManager, extensionManager }, ctx, evt) { function _askTrackMeasurements(uiViewportDialogService, viewportId) { return new Promise(function (resolve, reject) { - const message = 'Track measurements for this series?'; + const message = i18n.t('MeasurementTable:Track measurements for this series?'); const actions = [ { id: 'prompt-begin-tracking-cancel', type: ButtonEnums.type.secondary, - text: 'No', + text: i18n.t('Common:No'), value: RESPONSE.CANCEL, }, { id: 'prompt-begin-tracking-no-do-not-ask-again', type: ButtonEnums.type.secondary, - text: 'No, do not ask again', + text: i18n.t('MeasurementTable:No, do not ask again'), value: RESPONSE.NO_NEVER, }, { id: 'prompt-begin-tracking-yes', type: ButtonEnums.type.primary, - text: 'Yes', + text: i18n.t('Common:Yes'), value: RESPONSE.SET_STUDY_AND_SERIES, }, ]; diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewStudy.js b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewStudy.js index 03080ce90e0..23ea2b11eb9 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewStudy.js +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewStudy.js @@ -1,3 +1,5 @@ +import i18n from 'i18next'; + const RESPONSE = { NO_NEVER: -1, CANCEL: 0, @@ -32,17 +34,17 @@ function promptTrackNewStudy({ servicesManager, extensionManager }, ctx, evt) { function _askTrackMeasurements(UIViewportDialogService, viewportId) { return new Promise(function (resolve, reject) { - const message = 'Track measurements for this series?'; + const message = i18n.t('MeasurementTable:Track measurements for this series?'); const actions = [ - { type: 'cancel', text: 'No', value: RESPONSE.CANCEL }, + { type: 'cancel', text: i18n.t('MeasurementTable:No'), value: RESPONSE.CANCEL }, { type: 'secondary', - text: 'No, do not ask again for this series', + text: i18n.t('MeasurementTable:No, do not ask again'), value: RESPONSE.NO_NOT_FOR_SERIES, }, { type: 'primary', - text: 'Yes', + text: i18n.t('MeasurementTable:Yes'), value: RESPONSE.SET_STUDY_AND_SERIES, }, ]; diff --git a/extensions/measurement-tracking/src/getPanelModule.tsx b/extensions/measurement-tracking/src/getPanelModule.tsx index 6d7a906333e..a49a44a5bf6 100644 --- a/extensions/measurement-tracking/src/getPanelModule.tsx +++ b/extensions/measurement-tracking/src/getPanelModule.tsx @@ -1,5 +1,6 @@ import { Types } from '@ohif/core'; import { PanelMeasurementTableTracking, PanelStudyBrowserTracking } from './panels'; +import i18n from 'i18next'; // TODO: // - No loading UI exists yet @@ -11,7 +12,7 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager }): name: 'seriesList', iconName: 'tab-studies', iconLabel: 'Studies', - label: 'Studies', + label: i18n.t('SidePanel:Studies'), component: PanelStudyBrowserTracking.bind(null, { commandsManager, extensionManager, @@ -23,7 +24,7 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager }): name: 'trackedMeasurements', iconName: 'tab-linear', iconLabel: 'Measure', - label: 'Measurements', + label: i18n.t('SidePanel:Measurements'), component: PanelMeasurementTableTracking.bind(null, { commandsManager, extensionManager, diff --git a/extensions/measurement-tracking/src/viewports/TrackedCornerstoneViewport.tsx b/extensions/measurement-tracking/src/viewports/TrackedCornerstoneViewport.tsx index aed9f656357..759460144b8 100644 --- a/extensions/measurement-tracking/src/viewports/TrackedCornerstoneViewport.tsx +++ b/extensions/measurement-tracking/src/viewports/TrackedCornerstoneViewport.tsx @@ -222,10 +222,10 @@ function TrackedCornerstoneViewport(props) { patientAge: PatientAge || '', MRN: PatientID || '', thickness: SliceThickness ? `${parseFloat(SliceThickness).toFixed(2)}` : '', - thicknessUnits: 'mm', + thicknessUnits: t('mm'), spacing: SpacingBetweenSlices !== undefined - ? `${parseFloat(SpacingBetweenSlices).toFixed(2)}mm` + ? `${parseFloat(SpacingBetweenSlices).toFixed(2)}${t('mm')}` : '', scanner: ManufacturerModelName || '', }, @@ -312,6 +312,7 @@ function _getNextMeasurementUID( } function _getStatusComponent(isTracked) { + const { t } = useTranslation('TrackedCornerstoneViewport'); const trackedIcon = isTracked ? 'status-tracked' : 'status-untracked'; return ( @@ -330,15 +331,11 @@ function _getStatusComponent(isTracked) { {isTracked ? ( <> - Series is - tracked and can be viewed
{' '} - in the measurement panel + {t('Series is tracked and can be viewed in the measurement panel')} ) : ( <> - Measurements for - untracked - series
will not be shown in the
measurements panel + {t('Measurements for untracked series will not be shown in the measurements panel')} )}
diff --git a/modes/basic-dev-mode/src/index.js b/modes/basic-dev-mode/src/index.js index 411409e1f49..01513492fea 100644 --- a/modes/basic-dev-mode/src/index.js +++ b/modes/basic-dev-mode/src/index.js @@ -1,6 +1,7 @@ import toolbarButtons from './toolbarButtons.js'; import { hotkeys } from '@ohif/core'; import { id } from './id'; +import i18n from 'i18next'; const configs = { Length: {}, @@ -45,7 +46,7 @@ function modeFactory({ modeConfiguration }) { return { id, routeName: 'dev', - displayName: 'Basic Dev Viewer', + displayName: i18n.t('Modes:Basic Dev Viewer'), /** * Lifecycle hooks */ diff --git a/modes/basic-test-mode/src/index.ts b/modes/basic-test-mode/src/index.ts index 1c8d5fc8bb9..1c434217936 100644 --- a/modes/basic-test-mode/src/index.ts +++ b/modes/basic-test-mode/src/index.ts @@ -4,6 +4,7 @@ import { id } from './id'; import initToolGroups from './initToolGroups'; import moreTools from './moreTools'; import moreToolsMpr from './moreToolsMpr'; +import i18n from 'i18next'; // Allow this mode by excluding non-imaging modalities such as SR, SEG // Also, SM is not a simple imaging modalities, so exclude it. @@ -63,7 +64,7 @@ function modeFactory() { // We should not be. id, routeName: 'basic-test', - displayName: 'Basic Test Mode', + displayName: i18n.t('Modes:Basic Test Mode'), /** * Lifecycle hooks */ diff --git a/modes/longitudinal/src/index.js b/modes/longitudinal/src/index.js index 03f7fce9c91..8cca53bc527 100644 --- a/modes/longitudinal/src/index.js +++ b/modes/longitudinal/src/index.js @@ -4,6 +4,7 @@ import { id } from './id'; import initToolGroups from './initToolGroups'; import moreTools from './moreTools'; import moreToolsMpr from './moreToolsMpr'; +import i18n from 'i18next'; // Allow this mode by excluding non-imaging modalities such as SR, SEG // Also, SM is not a simple imaging modalities, so exclude it. @@ -69,7 +70,7 @@ function modeFactory({ modeConfiguration }) { // We should not be. id, routeName: 'viewer', - displayName: 'Basic Viewer', + displayName: i18n.t('Modes:Basic Viewer'), /** * Lifecycle hooks */ diff --git a/modes/microscopy/src/index.tsx b/modes/microscopy/src/index.tsx index 5f170ca265d..7165b7cc39c 100644 --- a/modes/microscopy/src/index.tsx +++ b/modes/microscopy/src/index.tsx @@ -1,4 +1,5 @@ import { hotkeys } from '@ohif/core'; +import i18n from 'i18next'; import { id } from './id'; import toolbarButtons from './toolbarButtons'; @@ -41,7 +42,7 @@ function modeFactory({ modeConfiguration }) { // We should not be. id, routeName: 'microscopy', - displayName: 'Microscopy', + displayName: i18n.t('Modes:Microscopy'), /** * Lifecycle hooks diff --git a/modes/segmentation/src/index.tsx b/modes/segmentation/src/index.tsx index 8b24196f161..7e00a266aec 100644 --- a/modes/segmentation/src/index.tsx +++ b/modes/segmentation/src/index.tsx @@ -2,6 +2,7 @@ import { hotkeys } from '@ohif/core'; import { id } from './id'; import toolbarButtons from './toolbarButtons'; import initToolGroups from './initToolGroups'; +import i18n from 'i18next'; const ohif = { layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout', @@ -44,7 +45,7 @@ function modeFactory({ modeConfiguration }) { * Mode name, which is displayed in the viewer's UI in the workList, for the * user to select the mode. */ - displayName: 'Segmentation', + displayName: i18n.t('Modes:Segmentation'), /** * Runs when the Mode Route is mounted to the DOM. Usually used to initialize * Services and other resources. diff --git a/modes/tmtv/src/index.js b/modes/tmtv/src/index.js index 110fb0fb753..dd57be35e06 100644 --- a/modes/tmtv/src/index.js +++ b/modes/tmtv/src/index.js @@ -4,6 +4,7 @@ import { id } from './id.js'; import initToolGroups, { toolGroupIds } from './initToolGroups.js'; import setCrosshairsConfiguration from './utils/setCrosshairsConfiguration.js'; import setFusionActiveVolume from './utils/setFusionActiveVolume.js'; +import i18n from 'i18next'; const { MetadataProvider } = classes; @@ -38,7 +39,7 @@ function modeFactory({ modeConfiguration }) { // We should not be. id, routeName: 'tmtv', - displayName: 'Total Metabolic Tumor Volume', + displayName: i18n.t('Modes:Total Metabolic Tumor Volume'), /** * Lifecycle hooks */ diff --git a/platform/app/src/routes/WorkList/WorkList.tsx b/platform/app/src/routes/WorkList/WorkList.tsx index fa236ce701e..ae518a29611 100644 --- a/platform/app/src/routes/WorkList/WorkList.tsx +++ b/platform/app/src/routes/WorkList/WorkList.tsx @@ -390,7 +390,7 @@ function WorkList({ onClick={() => {}} data-cy={`mode-${mode.routeName}-${studyInstanceUid}`} > - {t(`Modes:${mode.displayName}`)} + {mode.displayName} ) diff --git a/platform/core/src/utils/formatDate.js b/platform/core/src/utils/formatDate.js index 7b44277f200..866a9285af9 100644 --- a/platform/core/src/utils/formatDate.js +++ b/platform/core/src/utils/formatDate.js @@ -1,4 +1,5 @@ import moment from 'moment'; +import i18n from 'i18next'; /** * Format date @@ -7,7 +8,7 @@ import moment from 'moment'; * @param {string} format Desired date format * @returns {string} Formatted date */ -export default (date, format = 'DD-MMM-YYYY') => { +export default (date, format = i18n.t('Common:localDateFormat','DD-MMM-YYYY')) => { // moment(undefined) returns the current date, so return the empty string instead return date ? moment(date).format(format) : ''; }; diff --git a/platform/i18n/src/locales/en-US/Common.json b/platform/i18n/src/locales/en-US/Common.json index 2a9b748c32a..2cbb92cd38f 100644 --- a/platform/i18n/src/locales/en-US/Common.json +++ b/platform/i18n/src/locales/en-US/Common.json @@ -4,8 +4,10 @@ "Layout": "Layout", "LOAD": "LOAD", "Measurements": "Measurements", + "mm": "mm", "More": "More", "Next": "Next", + "No": "No", "NoStudyDate": "No Study Date", "Play": "Play", "Previous": "Previous", @@ -14,5 +16,6 @@ "Series": "Series", "Show": "Show", "Stop": "Stop", - "StudyDate": "Study Date" + "StudyDate": "Study Date", + "Yes": "Yes" } diff --git a/platform/i18n/src/locales/en-US/ErrorBoundary.json b/platform/i18n/src/locales/en-US/ErrorBoundary.json new file mode 100644 index 00000000000..dcefb50b4b7 --- /dev/null +++ b/platform/i18n/src/locales/en-US/ErrorBoundary.json @@ -0,0 +1,8 @@ +{ + "Context": "Context", + "Error Message": "Error Message", + "Something went wrong": "Something went wrong", + "in": "in", + "Sorry, something went wrong there. Try again.": "Sorry, something went wrong there. Try again.", + "Stack Trace": "Stack Trace" +} diff --git a/platform/i18n/src/locales/en-US/HotkeysValidators.json b/platform/i18n/src/locales/en-US/HotkeysValidators.json new file mode 100644 index 00000000000..74665c1ac0b --- /dev/null +++ b/platform/i18n/src/locales/en-US/HotkeysValidators.json @@ -0,0 +1,6 @@ +{ + "Field can't be empty": "Field can't be empty", + "Hotkey is already in use": "\"{{action}}\" is already using the \"{{pressedKeys}}\" shortcut.", + "It's not possible to define only modifier keys (ctrl, alt and shift) as a shortcut": "It's not possible to define only modifier keys (ctrl, alt and shift) as a shortcut", + "Shortcut combination is not allowed": "{{pressedKeys}} shortcut combination is not allowed" +} diff --git a/platform/i18n/src/locales/en-US/MeasurementTable.json b/platform/i18n/src/locales/en-US/MeasurementTable.json index d1f10950e2a..008a8c8a4dd 100644 --- a/platform/i18n/src/locales/en-US/MeasurementTable.json +++ b/platform/i18n/src/locales/en-US/MeasurementTable.json @@ -3,8 +3,10 @@ "Delete": "Delete", "Description": "Description", "MAX": "MAX", + "Measurements": "Measurements", + "No, do not ask again": "No, do not ask again", "NonTargets": "NonTargets", "Relabel": "Relabel", "Targets": "Targets", - "Measurements": "Measurements" + "Track measurements for this series?": "Track measurements for this series?" } diff --git a/platform/i18n/src/locales/en-US/Messages.json b/platform/i18n/src/locales/en-US/Messages.json index 130d2f97015..931bd939ad2 100644 --- a/platform/i18n/src/locales/en-US/Messages.json +++ b/platform/i18n/src/locales/en-US/Messages.json @@ -1,4 +1,5 @@ { + "Display Set Messages": "Display Set Messages", "1": "No valid instances found in series.", "2": "Display set has missing position information.", "3": "Display set is not a reconstructable 3D volume.", diff --git a/platform/i18n/src/locales/en-US/Modes.json b/platform/i18n/src/locales/en-US/Modes.json new file mode 100644 index 00000000000..813dfe9d63b --- /dev/null +++ b/platform/i18n/src/locales/en-US/Modes.json @@ -0,0 +1,8 @@ +{ + "Basic Dev Viewer": "Basic Dev Viewer", + "Basic Test Mode": "Basic Test Mode", + "Basic Viewer": "Basic Viewer", + "Microscopy": "Microscopy", + "Segmentation": "Segmentation", + "Total Metabolic Tumor Volume": "Total Metabolic Tumor Volume" +} diff --git a/platform/i18n/src/locales/en-US/SegmentationTable.json b/platform/i18n/src/locales/en-US/SegmentationTable.json new file mode 100644 index 00000000000..8d73016f326 --- /dev/null +++ b/platform/i18n/src/locales/en-US/SegmentationTable.json @@ -0,0 +1,18 @@ +{ + "Active": "Active", + "Add new segmentation": "Add new segmentation", + "Add segment": "Add segment", + "Add segmentation": "Add segmentation", + "Delete": "Delete", + "Display inactive segmentations": "Display inactive segmentations", + "Export DICOM SEG": "Export DICOM SEG", + "Download DICOM SEG": "Download DICOM SEG", + "Download DICOM RTSTRUCT": "Download DICOM RTSTRUCT", + "Fill": "Fill", + "Inactive segmentations": "Inactive segmentations", + "Opacity": "Opacity", + "Outline": "Outline", + "Rename": "Rename", + "Segmentation": "Segmentation", + "Size": "Size" +} diff --git a/platform/i18n/src/locales/en-US/StudyItem.json b/platform/i18n/src/locales/en-US/StudyItem.json new file mode 100644 index 00000000000..d6891379635 --- /dev/null +++ b/platform/i18n/src/locales/en-US/StudyItem.json @@ -0,0 +1,3 @@ +{ + "Tracked series": "{{trackedSeries}} Tracked series" +} diff --git a/platform/i18n/src/locales/en-US/StudyList.json b/platform/i18n/src/locales/en-US/StudyList.json index 9ee5a74fb4f..c64afdb7a3c 100644 --- a/platform/i18n/src/locales/en-US/StudyList.json +++ b/platform/i18n/src/locales/en-US/StudyList.json @@ -3,16 +3,18 @@ "ClearFilters": "Clear Filters", "Description": "Description", "Empty": "Empty", + "Filter list to 100 studies or less to enable sorting": "Filter the list to 100 studies or less to enable sorting", "Instances": "Instances", - "MRN": "MRN", - "NumOfStudiesHiggerThan100Message": "Filter the list to 100 studies or less to enable sorting", "Modality": "Modality", + "MRN": "MRN", + "Next": "Next >", + "No studies available": "No studies available", + "Number of studies": "Number of studies", + "Page": "Page", "PatientName": "Patient Name", "Previous": "< Back", - "Page": "Page", - "Next": "Next >", "Results per page": "Results per page", - "Number of studies": "Studies", "StudyDate": "Study Date", - "StudyList": "Study List" + "StudyList": "Study List", + "Upload": "Upload" } diff --git a/platform/i18n/src/locales/en-US/ThumbnailTracked.json b/platform/i18n/src/locales/en-US/ThumbnailTracked.json new file mode 100644 index 00000000000..0fef3468eec --- /dev/null +++ b/platform/i18n/src/locales/en-US/ThumbnailTracked.json @@ -0,0 +1,5 @@ +{ + "Series is tracked": "Series is tracked", + "Series is untracked": "Series is untracked", + "Viewport": "Viewport" +} diff --git a/platform/i18n/src/locales/en-US/TooltipClipboard.json b/platform/i18n/src/locales/en-US/TooltipClipboard.json new file mode 100644 index 00000000000..0d85da6610a --- /dev/null +++ b/platform/i18n/src/locales/en-US/TooltipClipboard.json @@ -0,0 +1,4 @@ +{ + "Copied": "Copied", + "Failed to copy": "Failed to copy" +} diff --git a/platform/i18n/src/locales/en-US/TrackedCornerstoneViewport.json b/platform/i18n/src/locales/en-US/TrackedCornerstoneViewport.json new file mode 100644 index 00000000000..6da525f3416 --- /dev/null +++ b/platform/i18n/src/locales/en-US/TrackedCornerstoneViewport.json @@ -0,0 +1,6 @@ +{ + "Series is tracked and can be viewed in the measurement panel": + "Series is tracked and can be viewed in the measurement panel", + "Measurements for untracked series will not be shown in the measurements panel": + "Measurements for untracked series will not be shown in the measurements panel" +} diff --git a/platform/i18n/src/locales/en-US/index.js b/platform/i18n/src/locales/en-US/index.js index d8b19e6f84f..eb3d442ba5c 100644 --- a/platform/i18n/src/locales/en-US/index.js +++ b/platform/i18n/src/locales/en-US/index.js @@ -4,11 +4,19 @@ import CineDialog from './CineDialog.json'; import Common from './Common.json'; import DataSourceConfiguration from './DataSourceConfiguration.json'; import DatePicker from './DatePicker.json'; +import ErrorBoundary from './ErrorBoundary.json'; import Header from './Header.json'; +import HotkeysValidators from './HotkeysValidators.json'; import MeasurementTable from './MeasurementTable.json'; +import Modes from './Modes.json'; +import SegmentationTable from './SegmentationTable.json'; import SidePanel from './SidePanel.json'; import StudyBrowser from './StudyBrowser.json'; +import StudyItem from './StudyItem.json'; import StudyList from './StudyList.json'; +import TooltipClipboard from './TooltipClipboard.json'; +import ThumbnailTracked from './ThumbnailTracked.json'; +import TrackedCornerstoneViewport from './TrackedCornerstoneViewport.json'; import UserPreferencesModal from './UserPreferencesModal.json'; import ViewportDownloadForm from './ViewportDownloadForm.json'; import Messages from './Messages.json'; @@ -21,11 +29,19 @@ export default { Common, DataSourceConfiguration, DatePicker, + ErrorBoundary, Header, + HotkeysValidators, MeasurementTable, + Modes, + SegmentationTable, SidePanel, StudyBrowser, + StudyItem, StudyList, + TooltipClipboard, + ThumbnailTracked, + TrackedCornerstoneViewport, UserPreferencesModal, ViewportDownloadForm, Messages, diff --git a/platform/i18n/src/locales/es/StudyList.json b/platform/i18n/src/locales/es/StudyList.json index eb1d970f005..8ff58c1a2b8 100644 --- a/platform/i18n/src/locales/es/StudyList.json +++ b/platform/i18n/src/locales/es/StudyList.json @@ -3,9 +3,9 @@ "ClearFilters": "Limpiar filtros", "Description": "Descripción", "Empty": "vacío", + "Filter list to 100 studies or less to enable sorting": "Filtre la lista a 100 estudios o menos para habilitar la clasificación", "Instances": "Instancias", "MRN": "MRN", - "NumOfStudiesHiggerThan100Message": "Filtre la lista a 100 estudios o menos para habilitar la clasificación", "Modality": "Modalidad", "PatientName": "Nombre paciente", "Previous": "< Anterior", diff --git a/platform/i18n/src/locales/test-LNG/Common.json b/platform/i18n/src/locales/test-LNG/Common.json index 9c29646fe74..a809080484e 100644 --- a/platform/i18n/src/locales/test-LNG/Common.json +++ b/platform/i18n/src/locales/test-LNG/Common.json @@ -3,8 +3,10 @@ "Image": "Test Image", "Layout": "Test Layout", "Measurements": "Test Measurements", + "mm": "Test mm", "More": "Test More", "Next": "Test Next", + "No": "Test No", "Play": "Test Play", "Previous": "Test Previous", "Reset": "Test Reset", @@ -12,5 +14,6 @@ "Series": "Test Series", "Show": "Test Show", "Stop": "Test Stop", - "StudyDate": "Test Study Date" + "StudyDate": "Test Study Date", + "Yes": "Test Yes" } diff --git a/platform/i18n/src/locales/test-LNG/ErrorBoundary.json b/platform/i18n/src/locales/test-LNG/ErrorBoundary.json new file mode 100644 index 00000000000..4077306b249 --- /dev/null +++ b/platform/i18n/src/locales/test-LNG/ErrorBoundary.json @@ -0,0 +1,8 @@ +{ + "Context": "Test Context", + "Error Message": "Test Error Message", + "Something went wrong": "Test Something went wrong", + "in": "in", + "Sorry, something went wrong there. Try again.": "Test Sorry, something went wrong there. Try again.", + "Stack Trace": "Test Stack Trace" +} diff --git a/platform/i18n/src/locales/test-LNG/HotkeysValidators.json b/platform/i18n/src/locales/test-LNG/HotkeysValidators.json new file mode 100644 index 00000000000..97348844000 --- /dev/null +++ b/platform/i18n/src/locales/test-LNG/HotkeysValidators.json @@ -0,0 +1,6 @@ +{ + "Field can't be empty": "Test Field can't be empty", + "Hotkey is already in use": "Test \"{{action}}\" is already using the \"{{pressedKeys}}\" shortcut.", + "It's not possible to define only modifier keys (ctrl, alt and shift) as a shortcut": "Test It's not possible to define only modifier keys (ctrl, alt and shift) as a shortcut", + "Shortcut combination is not allowed": "Test {{pressedKeys}} shortcut combination is not allowed" +} diff --git a/platform/i18n/src/locales/test-LNG/MeasurementTable.json b/platform/i18n/src/locales/test-LNG/MeasurementTable.json index 70e04dea018..f65da4815e1 100644 --- a/platform/i18n/src/locales/test-LNG/MeasurementTable.json +++ b/platform/i18n/src/locales/test-LNG/MeasurementTable.json @@ -6,7 +6,9 @@ "Delete": "Delete", "Description": "Description", "MAX": "MAX", + "No, do not ask again": "Test No, do not ask again", "NonTargets": "NonTargets", "Relabel": "Relabel", - "Targets": "Targets" + "Targets": "Targets", + "Track measurements for this series?": "Test Track measurements for this series?" } diff --git a/platform/i18n/src/locales/test-LNG/Messages.json b/platform/i18n/src/locales/test-LNG/Messages.json new file mode 100644 index 00000000000..acf153cac98 --- /dev/null +++ b/platform/i18n/src/locales/test-LNG/Messages.json @@ -0,0 +1,16 @@ +{ + "Display Set Messages": "Test Display Set Messages", + "1": "Test No valid instances found in series.", + "2": "Test Display set has missing position information.", + "3": "Test Display set is not a reconstructable 3D volume.", + "4": "Test Multi frame display sets do not have pixel measurement information.", + "5": "Test Multi frame display sets do not have orientation information.", + "6": "Test Multi frame display sets do not have position information.", + "7": "Test Display set has missing frames.", + "8": "Test Display set has irregular spacing.", + "9": "Test Display set has inconsistent dimensions between frames.", + "10": "Test Display set has frames with inconsistent number of components.", + "11": "Test Display set has frames with inconsistent orientations.", + "12": "Test Display set has inconsistent position information.", + "13": "Test Unsupported display set." +} diff --git a/platform/i18n/src/locales/test-LNG/Modes.json b/platform/i18n/src/locales/test-LNG/Modes.json index 058e7d5c224..a9f03e23274 100644 --- a/platform/i18n/src/locales/test-LNG/Modes.json +++ b/platform/i18n/src/locales/test-LNG/Modes.json @@ -1,3 +1,8 @@ { - "Basic Viewer": "Test Basic Viewer" + "Basic Dev Viewer": "Test Basic Dev Viewer", + "Basic Test Mode": "Test Basic Test Mode", + "Basic Viewer": "Test Basic Viewer", + "Microscopy": "Test Microscopy", + "Segmentation": "Test Segmentation", + "Total Metabolic Tumor Volume": "Test Total Metabolic Tumor Volume" } diff --git a/platform/i18n/src/locales/test-LNG/SegmentationTable.json b/platform/i18n/src/locales/test-LNG/SegmentationTable.json new file mode 100644 index 00000000000..45f6aae720b --- /dev/null +++ b/platform/i18n/src/locales/test-LNG/SegmentationTable.json @@ -0,0 +1,18 @@ +{ + "Active": "Test Active", + "Add new segmentation": "Test Add new segmentation", + "Add segment": "Test Add segment", + "Add segmentation": "Test Add segmentation", + "Delete": "Test Delete", + "Display inactive segmentations": "Test Display inactive segmentations", + "Export DICOM SEG": "Test Export DICOM SEG", + "Download DICOM SEG": "Test Download DICOM SEG", + "Download DICOM RTSTRUCT": "Test Download DICOM RTSTRUCT", + "Fill": "Test Fill", + "Inactive segmentations": "Test Inactive segmentations", + "Opacity": "Test Opacity", + "Outline": "Test Outline", + "Rename": "Test Rename", + "Segmentation": "Test Segmentation", + "Size": "Test Size" +} diff --git a/platform/i18n/src/locales/test-LNG/StudyItem.json b/platform/i18n/src/locales/test-LNG/StudyItem.json new file mode 100644 index 00000000000..b8a18966dfa --- /dev/null +++ b/platform/i18n/src/locales/test-LNG/StudyItem.json @@ -0,0 +1,3 @@ +{ + "Tracked series": "{{trackedSeries}} Test Tracked series" +} diff --git a/platform/i18n/src/locales/test-LNG/StudyList.json b/platform/i18n/src/locales/test-LNG/StudyList.json index ea4b3007595..5f9bf949f94 100644 --- a/platform/i18n/src/locales/test-LNG/StudyList.json +++ b/platform/i18n/src/locales/test-LNG/StudyList.json @@ -1,21 +1,23 @@ { + "Previous": "Test < Previous", "AccessionNumber": "Test Accession #", "Accession": "Test Accession", - "Next >": "Test Next >", - "< Previous": "Test < Previous", - "Results per page": "Test Results per page", + "Description": "Test Description", "Empty": "Test Empty", + "Filter list to 100 studies or less to enable sorting": "Test Filter list to 100 studies or less to enable sorting", + "Instances": "Test Instances", "MRN": "Test MRN", "Modality": "Test Modality", + "Next": "Test Next >", + "No studies available": "Test No studies available", + "Number of studies": "Test Number of studies", "PatientName": "Test PatientName", "Patient Name": "Test Patient Name", - "Description": "Test Description", + "Results per page": "Test Results per page", "StudyDate": "Test Study Date", "Study date": "Test Study Date", - "Number of studies": "Test Studies", "Series": "Test Series", - "Instances": "Test Instances", "Study List": "Test Study List", "Study list": "Test Study list", - "Filter list to 100 studies or less to enable sorting": "Test Filter list to 100 studies or less to enable sorting" + "Upload": "Test Upload" } diff --git a/platform/i18n/src/locales/test-LNG/ThumbnailTracked.json b/platform/i18n/src/locales/test-LNG/ThumbnailTracked.json new file mode 100644 index 00000000000..bfda28677f6 --- /dev/null +++ b/platform/i18n/src/locales/test-LNG/ThumbnailTracked.json @@ -0,0 +1,5 @@ +{ + "Series is tracked": "Test Series is tracked", + "Series is untracked": "Test Series is untracked", + "Viewport": "Test Viewport" +} diff --git a/platform/i18n/src/locales/test-LNG/TooltipClipboard.json b/platform/i18n/src/locales/test-LNG/TooltipClipboard.json new file mode 100644 index 00000000000..b21a54d518c --- /dev/null +++ b/platform/i18n/src/locales/test-LNG/TooltipClipboard.json @@ -0,0 +1,4 @@ +{ + "Copied": "Test Copied", + "Failed to copy": "Test Failed to copy" +} diff --git a/platform/i18n/src/locales/test-LNG/TrackedCornerstoneViewport.json b/platform/i18n/src/locales/test-LNG/TrackedCornerstoneViewport.json new file mode 100644 index 00000000000..2b6c50e8aa5 --- /dev/null +++ b/platform/i18n/src/locales/test-LNG/TrackedCornerstoneViewport.json @@ -0,0 +1,6 @@ +{ + "Series is tracked and can be viewed in the measurement panel": + "Test Series is tracked and can be viewed in the measurement panel", + "Measurements for untracked series will not be shown in the measurements panel": + "Test Measurements for untracked series will not be shown in the measurements panel" +} diff --git a/platform/i18n/src/locales/test-LNG/index.js b/platform/i18n/src/locales/test-LNG/index.js index f39132793b7..561161d2f20 100644 --- a/platform/i18n/src/locales/test-LNG/index.js +++ b/platform/i18n/src/locales/test-LNG/index.js @@ -3,17 +3,25 @@ import Buttons from './Buttons.json'; import CineDialog from './CineDialog.json'; import Common from './Common.json'; import DatePicker from './DatePicker.json'; +import ErrorBoundary from './ErrorBoundary.json'; import Header from './Header.json'; +import HotkeysValidators from './HotkeysValidators.json'; import MeasurementTable from './MeasurementTable.json'; +import Messages from './Messages.json'; +import Modals from './Modals.json'; +import Modes from './Modes.json'; +import PatientInfo from './PatientInfo.json'; +import SegmentationTable from './SegmentationTable.json'; +import SidePanel from './SidePanel.json'; +import StudyBrowser from './StudyBrowser.json'; +import StudyItem from './StudyItem.json'; import StudyList from './StudyList.json'; +import ToolTip from './ToolTip.json'; +import TooltipClipboard from './TooltipClipboard.json'; +import ThumbnailTracked from './ThumbnailTracked.json'; +import TrackedCornerstoneViewport from './TrackedCornerstoneViewport.json'; import UserPreferencesModal from './UserPreferencesModal.json'; import ViewportDownloadForm from './ViewportDownloadForm.json'; -import ToolTip from './ToolTip.json'; -import StudyBrowser from './StudyBrowser.json'; -import SidePanel from './SidePanel.json'; -import PatientInfo from './PatientInfo.json'; -import Modes from './Modes.json'; -import Modals from './Modals.json'; export default { 'test-LNG': { @@ -22,16 +30,24 @@ export default { CineDialog, Common, DatePicker, + ErrorBoundary, Header, + HotkeysValidators, MeasurementTable, + Messages, + Modals, + Modes, + PatientInfo, + SegmentationTable, + SidePanel, + StudyBrowser, + StudyItem, StudyList, + ToolTip, + TooltipClipboard, + ThumbnailTracked, + TrackedCornerstoneViewport, UserPreferencesModal, ViewportDownloadForm, - ToolTip, - StudyBrowser, - PatientInfo, - Modes, - SidePanel, - Modals, }, }; diff --git a/platform/i18n/src/locales/zh/StudyList.json b/platform/i18n/src/locales/zh/StudyList.json index 478d3f80299..bbdf8bea732 100644 --- a/platform/i18n/src/locales/zh/StudyList.json +++ b/platform/i18n/src/locales/zh/StudyList.json @@ -1,5 +1,6 @@ { "Empty": "无", + "Filter list to 100 studies or less to enable sorting": "将检查列表过滤到 100 个或更少以启用排序", "Modality": "成像设备", "PatientName": "患者姓名", "StudyDate": "检查日期", @@ -14,14 +15,13 @@ "Instances": "图像数", "Accession": "检查号", "Results per page": "每页条数", - "< Previous": "上一页", - "Next >": "下一页", + "Previous": "上一页", + "Next": "下一页", "Page": "页码", "Start Date": "开始日期", "Series": "序列", "No studies available": "没有数据", "Loading...": "加载中...", "Select...": "选择...", - "InstitutionName": "检查机构", - "Filter list to 100 studies or less to enable sorting": "将检查列表过滤到 100 个或更少以启用排序" + "InstitutionName": "检查机构" } diff --git a/platform/ui/src/components/DisplaySetMessageListTooltip/DisplaySetMessageListTooltip.tsx b/platform/ui/src/components/DisplaySetMessageListTooltip/DisplaySetMessageListTooltip.tsx index 781742edcac..4d1c4102de6 100644 --- a/platform/ui/src/components/DisplaySetMessageListTooltip/DisplaySetMessageListTooltip.tsx +++ b/platform/ui/src/components/DisplaySetMessageListTooltip/DisplaySetMessageListTooltip.tsx @@ -37,7 +37,7 @@ const DisplaySetMessageListTooltip = ({ messages, id }): React.ReactNode => { marginTop: '12px', }} > - Display Set Messages + {t('Display Set Messages')}
    { + const { t } = useTranslation('StudyList'); return (
    { className="text-primary-light" variant="h5" > - {'No studies available'} + {t('No studies available')}
    ); diff --git a/platform/ui/src/components/ErrorBoundary/ErrorBoundary.tsx b/platform/ui/src/components/ErrorBoundary/ErrorBoundary.tsx index a485590e2a7..c8170e60d20 100644 --- a/platform/ui/src/components/ErrorBoundary/ErrorBoundary.tsx +++ b/platform/ui/src/components/ErrorBoundary/ErrorBoundary.tsx @@ -1,6 +1,8 @@ import React, { useState } from 'react'; import { ErrorBoundary as ReactErrorBoundary } from 'react-error-boundary'; import PropTypes from 'prop-types'; +import { useTranslation } from 'react-i18next'; +import i18n from 'i18next'; import Modal from '../Modal'; import Icon from '../Icon'; @@ -9,9 +11,10 @@ import IconButton from '../IconButton'; const isProduction = process.env.NODE_ENV === 'production'; const DefaultFallback = ({ error, context, resetErrorBoundary, fallbackRoute }) => { + const { t } = useTranslation('ErrorBoundary'); const [showDetails, setShowDetails] = useState(false); - const title = `Something went wrong${!isProduction && ` in ${context}`}.`; - const subtitle = `Sorry, something went wrong there. Try again.`; + const title = `${t('Something went wrong')}${!isProduction && ` ${t('in')} ${context}`}.`; + const subtitle = t('Sorry, something went wrong there. Try again.'); return (
    {subtitle}

    {!isProduction && (
    -

    Context: {context}

    -

    Error Message: {error.message}

    +

    {t('Context')}: {context}

    +

    {t('Error Message')}: {error.message}

    setShowDetails(!showDetails)} > -
    {'Stack Trace'}
    +
    {t('Stack Trace')}
    { setIsOpen(false); if (fallbackRoute && typeof window !== 'undefined') { diff --git a/platform/ui/src/components/HotkeysPreferences/hotkeysValidators.js b/platform/ui/src/components/HotkeysPreferences/hotkeysValidators.js index be56d247eb8..0df0f5dee55 100644 --- a/platform/ui/src/components/HotkeysPreferences/hotkeysValidators.js +++ b/platform/ui/src/components/HotkeysPreferences/hotkeysValidators.js @@ -1,4 +1,5 @@ import { MODIFIER_KEYS, DISALLOWED_COMBINATIONS } from './hotkeysConfig'; +import i18n from 'i18next'; const formatPressedKeys = pressedKeysArray => pressedKeysArray.join('+'); @@ -20,8 +21,8 @@ const findConflictingCommand = (hotkeys, currentCommandName, pressedKeys) => { }; const ERROR_MESSAGES = { - MODIFIER: "It's not possible to define only modifier keys (ctrl, alt and shift) as a shortcut", - EMPTY: "Field can't be empty.", + MODIFIER: i18n.t('HotkeysValidators:It\'s not possible to define only modifier keys (ctrl, alt and shift) as a shortcut'), + EMPTY: i18n.t('HotkeysValidators:Field can\'t be empty'), }; // VALIDATORS @@ -46,7 +47,7 @@ const conflictingValidator = ({ commandName, pressedKeys, hotkeys }) => { if (conflictingCommand) { return { - error: `"${conflictingCommand.label}" is already using the "${pressedKeys}" shortcut.`, + error: i18n.t('HotkeysValidators:Hotkey is already in use', {action: conflictingCommand.label, pressedKeys: pressedKeys }), }; } }; @@ -62,7 +63,7 @@ const disallowedValidator = ({ pressedKeys = [] }) => { if (hasDisallowedCombinations) { return { - error: `"${formatPressedKeys(pressedKeys)}" shortcut combination is not allowed`, + error: i18n.t('HotkeysValidators:Shortcut combination is not allowed', {pressedKeys: formatPressedKeys(pressedKeys)}), }; } }; diff --git a/platform/ui/src/components/SegmentationGroupTable/AddSegmentRow.tsx b/platform/ui/src/components/SegmentationGroupTable/AddSegmentRow.tsx index ed806c76f43..c5071495581 100644 --- a/platform/ui/src/components/SegmentationGroupTable/AddSegmentRow.tsx +++ b/platform/ui/src/components/SegmentationGroupTable/AddSegmentRow.tsx @@ -1,7 +1,9 @@ import React from 'react'; import Icon from '../Icon'; +import { useTranslation } from 'react-i18next'; function AddSegmentRow({ onClick }) { + const { t } = useTranslation('SegmentationTable'); return (
    - Add Segment + {t('Add segment')}
    diff --git a/platform/ui/src/components/SegmentationGroupTable/NoSegmentationRow.tsx b/platform/ui/src/components/SegmentationGroupTable/NoSegmentationRow.tsx index 05233dcc011..5e6b74e1943 100644 --- a/platform/ui/src/components/SegmentationGroupTable/NoSegmentationRow.tsx +++ b/platform/ui/src/components/SegmentationGroupTable/NoSegmentationRow.tsx @@ -1,7 +1,9 @@ import React from 'react'; import Icon from '../Icon'; +import { useTranslation } from 'react-i18next'; function NoSegmentationRow({ onSegmentationAdd }) { + const { t } = useTranslation('SegmentationTable'); return (
    - Add Segmentation + {t('Add segmentation')} ); diff --git a/platform/ui/src/components/SegmentationGroupTable/SegmentationConfig.tsx b/platform/ui/src/components/SegmentationGroupTable/SegmentationConfig.tsx index c56260c3130..622b9219661 100644 --- a/platform/ui/src/components/SegmentationGroupTable/SegmentationConfig.tsx +++ b/platform/ui/src/components/SegmentationGroupTable/SegmentationConfig.tsx @@ -4,6 +4,7 @@ import InputRange from '../InputRange'; import CheckBox from '../CheckBox'; import InputNumber from '../InputNumber'; import classNames from 'classnames'; +import { useTranslation } from 'react-i18next'; const getRoundedValue = value => { return Math.round(value * 100) / 100; @@ -17,19 +18,20 @@ const ActiveSegmentationConfig = ({ setRenderFill, setFillAlpha, }) => { + const { t } = useTranslation('SegmentationTable'); return (
    -
    Active
    +
    {t('Active')}
    -
    Opacity
    +
    {t('Opacity')}
    -
    Size
    +
    {t('Size')}
    { + const { t } = useTranslation('SegmentationTable'); return (
    - Opacity + {t('Opacity')} { + const { t } = useTranslation('SegmentationTable'); const { initialConfig } = segmentationConfig; const [isMinimized, setIsMinimized] = useState(true); return ( @@ -144,7 +148,7 @@ const SegmentationConfig = ({ 'rotate-90 transform': !isMinimized, })} /> - {'Inactive Segmentations'} + {t('Inactive segmentations')}
    {!isMinimized && ( { onSegmentationAdd(); }, @@ -56,7 +58,7 @@ function SegmentationDropDownRow({ ...(!disableEditing ? [ { - title: 'Rename', + title: t('Rename'), onClick: () => { onSegmentationEdit(activeSegmentation.id); }, @@ -64,7 +66,7 @@ function SegmentationDropDownRow({ ] : []), { - title: 'Delete', + title: t('Delete'), onClick: () => { onSegmentationDelete(activeSegmentation.id); }, @@ -72,7 +74,7 @@ function SegmentationDropDownRow({ ...(!disableEditing ? [ { - title: 'Export DICOM SEG', + title: t('Export DICOM SEG'), onClick: () => { storeSegmentation(activeSegmentation.id); }, @@ -81,13 +83,13 @@ function SegmentationDropDownRow({ : []), ...[ { - title: 'Download DICOM SEG', + title: t('Download DICOM SEG'), onClick: () => { onSegmentationDownload(activeSegmentation.id); }, }, { - title: 'Download DICOM RTSTRUCT', + title: t('Download DICOM RTSTRUCT'), onClick: () => { onSegmentationDownloadRTSS(activeSegmentation.id); }, diff --git a/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTable.tsx b/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTable.tsx index 295a7951441..2ea0bcb0014 100644 --- a/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTable.tsx +++ b/platform/ui/src/components/SegmentationGroupTable/SegmentationGroupTable.tsx @@ -6,6 +6,7 @@ import SegmentationDropDownRow from './SegmentationDropDownRow'; import NoSegmentationRow from './NoSegmentationRow'; import AddSegmentRow from './AddSegmentRow'; import SegmentationGroupSegment from './SegmentationGroupSegment'; +import { useTranslation } from 'react-i18next'; const SegmentationGroupTable = ({ segmentations, @@ -70,11 +71,12 @@ const SegmentationGroupTable = ({ const activeSegmentation = segmentations?.find( segmentation => segmentation.id === activeSegmentationId ); + const { t } = useTranslation('SegmentationTable'); return (
    { }; const SidePanel = ({ side, className, activeTabIndex: activeTabIndexProp, tabs, onOpen }) => { - const { t } = useTranslation('SidePanel'); - const [panelOpen, setPanelOpen] = useState(activeTabIndexProp !== null); const [activeTabIndex, setActiveTabIndex] = useState(0); diff --git a/platform/ui/src/components/StudyItem/StudyItem.tsx b/platform/ui/src/components/StudyItem/StudyItem.tsx index 6e7804fab1d..9325e5b013e 100644 --- a/platform/ui/src/components/StudyItem/StudyItem.tsx +++ b/platform/ui/src/components/StudyItem/StudyItem.tsx @@ -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 '../Icon'; @@ -16,6 +17,7 @@ const StudyItem = ({ isActive, onClick, }) => { + const { t } = useTranslation('StudyItem'); return (
    - {trackedSeries} Tracked Series + {t('Tracked series', {trackedSeries: trackedSeries})}
    )} diff --git a/platform/ui/src/components/StudyListFilter/StudyListFilter.tsx b/platform/ui/src/components/StudyListFilter/StudyListFilter.tsx index 8db3d8393fd..b322eba176a 100644 --- a/platform/ui/src/components/StudyListFilter/StudyListFilter.tsx +++ b/platform/ui/src/components/StudyListFilter/StudyListFilter.tsx @@ -48,7 +48,7 @@ const StudyListFilter = ({ onClick={onUploadClick} > - Upload + {t('Upload')}
    )}
    @@ -69,16 +69,16 @@ const StudyListFilter = ({ )} - {numOfStudies > 100 ? '>100' : numOfStudies} + {`${t('Number of studies')}: `} - {t('Number of studies')} + {numOfStudies > 100 ? '>100' : numOfStudies}
    @@ -99,7 +99,7 @@ const StudyListFilter = ({ {numOfStudies > 100 && (
    -

    {t('NumOfStudiesHiggerThan100Message')}

    +

    {t('Filter list to 100 studies or less to enable sorting')}

    )} diff --git a/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx b/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx index 0f56e20ee7e..2db59fb64ea 100644 --- a/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx +++ b/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.tsx @@ -6,8 +6,9 @@ import Icon from '../Icon'; import Thumbnail from '../Thumbnail'; import Tooltip from '../Tooltip'; import { StringNumber } from '../../types'; +import { useTranslation } from 'react-i18next'; -const ThumbnailTracked = ({ +function ThumbnailTracked ({ displaySetInstanceUID, className, imageSrc, @@ -24,7 +25,8 @@ const ThumbnailTracked = ({ viewportIdentificator, isTracked, isActive, -}) => { +}) { + const { t } = useTranslation('ThumbnailTracked'); const trackedIcon = isTracked ? 'circled-checkmark' : 'dotted-circle'; const viewportIdentificatorLabel = viewportIdentificator.join(', '); const renderViewportLabels = () => { @@ -42,7 +44,7 @@ const ThumbnailTracked = ({ position="right" content={
    - Series is displayed
    in viewport {viewportIdentificatorLabel} + {`${t('Viewport')}: ${viewportIdentificatorLabel}`}
    } > @@ -85,13 +87,11 @@ const ThumbnailTracked = ({
    - Series is - {isTracked ? ' tracked' : ' untracked'} + {isTracked ? t('Series is tracked') : t('Series is untracked')} {!!viewportIdentificator.length && ( - in viewport - {viewportIdentificatorLabel} + {`${t('Viewport')}: ${viewportIdentificatorLabel}`} )}
    diff --git a/platform/ui/src/components/TooltipClipboard/TooltipClipboard.tsx b/platform/ui/src/components/TooltipClipboard/TooltipClipboard.tsx index 43688b90547..c48755363ed 100644 --- a/platform/ui/src/components/TooltipClipboard/TooltipClipboard.tsx +++ b/platform/ui/src/components/TooltipClipboard/TooltipClipboard.tsx @@ -1,4 +1,5 @@ import React, { useState, useRef, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; import PropTypes from 'prop-types'; import classnames from 'classnames'; @@ -9,6 +10,8 @@ const DELAY_TO_HIDE = 10; // it needs at least a little delay to prevent tooltip const DELAY_TO_HIDE_AFTER_COPYING = 1000; const TooltipClipboard = ({ children, text }) => { + const { t } = useTranslation('TooltipClipboard'); + const [isActive, setIsActive] = useState(false); const [message, setMessage] = useState(null); const [isCopying, setIsCopying] = useState(false); @@ -21,10 +24,10 @@ const TooltipClipboard = ({ children, text }) => { setIsCopying(true); try { await navigator.clipboard.writeText(text); - setMessage('Copied!'); + setMessage(t('Copied')); } catch (err) { console.error('Failed to copy: ', err); - setMessage('Failed to copy!'); + setMessage(t('Failed to copy')); } finally { refreshElementPosition();