diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/EditLabwareOffDeck.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/EditLabwareOffDeck.tsx index 50c190c6dc6..c923df5af15 100644 --- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/EditLabwareOffDeck.tsx +++ b/protocol-designer/src/components/DeckSetup/LabwareOverlays/EditLabwareOffDeck.tsx @@ -1,5 +1,6 @@ import * as React from 'react' import { connect } from 'react-redux' +import { useTranslation } from 'react-i18next' import { css } from 'styled-components' import { ALIGN_FLEX_START, @@ -12,7 +13,6 @@ import { SPACING, } from '@opentrons/components' import { getLabwareDisplayName } from '@opentrons/shared-data' -import { i18n } from '../../../localization' import { deleteContainer, duplicateLabware, @@ -80,7 +80,7 @@ const EditLabwareOffDeckComponent = (props: Props): JSX.Element => { deleteLabware, duplicateLabware, } = props - + const { t } = useTranslation('deck') const { isTiprack } = labwareEntity.def.parameters if (isYetUnnamed && !isTiprack) { return ( @@ -97,18 +97,18 @@ const EditLabwareOffDeckComponent = (props: Props): JSX.Element => { {!isTiprack ? ( - {i18n.t('deck.overlay.edit.name_and_liquids')} + {t('overlay.edit.name_and_liquids')} ) : (
)} - {i18n.t('deck.overlay.edit.duplicate')} + {t('overlay.edit.duplicate')} - {i18n.t('deck.overlay.edit.delete')} + {t('overlay.edit.delete')}
) diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/NameThisLabware.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/NameThisLabware.tsx index ae52627004a..90c9a623244 100644 --- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/NameThisLabware.tsx +++ b/protocol-designer/src/components/DeckSetup/LabwareOverlays/NameThisLabware.tsx @@ -1,9 +1,9 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import { connect } from 'react-redux' import cx from 'classnames' import { Icon, useOnClickOutside } from '@opentrons/components' import { renameLabware } from '../../../labware-ingred/actions' -import { i18n } from '../../../localization' import styles from './LabwareOverlays.css' import type { LabwareEntity } from '@opentrons/step-generation' import type { ThunkDispatch } from '../../../types' @@ -15,7 +15,6 @@ interface OP { } interface DP { - // TODO Ian 2018-02-16 type these fns elsewhere and import the type setLabwareName: (name: string | null | undefined) => unknown } @@ -23,6 +22,7 @@ type Props = OP & DP const NameThisLabwareComponent = (props: Props): JSX.Element => { const [inputValue, setInputValue] = React.useState('') + const { t } = useTranslation('deck') const saveNickname = (): void => { props.setLabwareName(inputValue || null) @@ -52,17 +52,17 @@ const NameThisLabwareComponent = (props: Props): JSX.Element => { className={styles.name_input} onChange={handleChange} onKeyUp={handleKeyUp} - placeholder={i18n.t('deck.overlay.name_labware.nickname_placeholder')} + placeholder={t('overlay.name_labware.nickname_placeholder')} value={inputValue} /> - {i18n.t('deck.overlay.name_labware.add_liquids')} + {t('overlay.name_labware.add_liquids')} - {i18n.t('deck.overlay.name_labware.leave_empty')} + {t('overlay.name_labware.leave_empty')} ) diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/SlotControls.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/SlotControls.tsx index b418c921397..8c299b54063 100644 --- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/SlotControls.tsx +++ b/protocol-designer/src/components/DeckSetup/LabwareOverlays/SlotControls.tsx @@ -1,11 +1,11 @@ import assert from 'assert' import * as React from 'react' +import { useTranslation } from 'react-i18next' import { connect } from 'react-redux' import noop from 'lodash/noop' import { DropTarget, DropTargetConnector, DropTargetMonitor } from 'react-dnd' import cx from 'classnames' import { Icon, RobotCoordsForeignDiv } from '@opentrons/components' -import { i18n } from '../../../localization' import { DND_TYPES } from '../../../constants' import { getLabwareIsCompatible, @@ -29,6 +29,7 @@ import type { } from '@opentrons/shared-data' import type { BaseState, DeckSlot, ThunkDispatch } from '../../../types' import type { LabwareOnDeck } from '../../../step-forms' + import styles from './LabwareOverlays.css' interface DNDP { @@ -74,6 +75,7 @@ export const SlotControlsComponent = ( itemType, customLabwareDefs, } = props + const { t } = useTranslation('deck') if ( selectedTerminalItemId !== START_TERMINAL_ITEM_ID || (itemType !== DND_TYPES.LABWARE && itemType !== null) || @@ -134,7 +136,7 @@ export const SlotControlsComponent = ( > {!isOver && } - {i18n.t(`deck.overlay.slot.${isOver ? 'place_here' : overlayText}`)} + {t(`overlay.slot.${isOver ? 'place_here' : overlayText}`)} )} diff --git a/protocol-designer/src/components/DeckSetup/NullDeckState.tsx b/protocol-designer/src/components/DeckSetup/NullDeckState.tsx index 81b137e0aa1..238fd9f3491 100644 --- a/protocol-designer/src/components/DeckSetup/NullDeckState.tsx +++ b/protocol-designer/src/components/DeckSetup/NullDeckState.tsx @@ -1,4 +1,5 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import { FONT_SIZE_BODY_1, FONT_WEIGHT_BOLD, @@ -7,7 +8,6 @@ import { RobotWorkSpace, TEXT_TRANSFORM_UPPERCASE, } from '@opentrons/components' -import { i18n } from '../../localization' import { VIEWBOX_HEIGHT, VIEWBOX_MIN_X, @@ -20,7 +20,7 @@ import styles from './DeckSetup.css' export const NullDeckState = (): JSX.Element => { const deckDef = React.useMemo(() => getDeckDefinitions().ot2_standard, []) - + const { t } = useTranslation('deck') return (
@@ -40,7 +40,7 @@ export const NullDeckState = (): JSX.Element => { fontWeight={FONT_WEIGHT_BOLD} fontSize={FONT_SIZE_BODY_1} > - {i18n.t('deck.inactive_deck')} + {t('inactive_deck')} )} diff --git a/protocol-designer/src/components/DeckSetup/SlotWarning.tsx b/protocol-designer/src/components/DeckSetup/SlotWarning.tsx index d5f33242a6f..dac3928bbc1 100644 --- a/protocol-designer/src/components/DeckSetup/SlotWarning.tsx +++ b/protocol-designer/src/components/DeckSetup/SlotWarning.tsx @@ -1,6 +1,6 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import styled from 'styled-components' -import { i18n } from '../../localization' import { RobotCoordsForeignDiv, TYPOGRAPHY } from '@opentrons/components' import type { ModuleOrientation } from '@opentrons/shared-data' @@ -27,7 +27,7 @@ export const SlotWarning = (props: Props): JSX.Element => { const { x, y, xDimension, yDimension, orientation, warningType } = props const rectXOffset = orientation === 'left' ? -OVERHANG : 0 const textXOffset = orientation === 'left' ? -1 * OVERHANG : xDimension - + const { t } = useTranslation('deck') return ( { width={OVERHANG} height={yDimension} > - {i18n.t(`deck.warning.${warningType}`)} + {t(`warning.${warningType}`)} ) diff --git a/protocol-designer/src/components/FileSidebar/FileSidebar.tsx b/protocol-designer/src/components/FileSidebar/FileSidebar.tsx index 60962e682e0..2f7076896f1 100644 --- a/protocol-designer/src/components/FileSidebar/FileSidebar.tsx +++ b/protocol-designer/src/components/FileSidebar/FileSidebar.tsx @@ -7,7 +7,6 @@ import { OutlineButton, SidePanel, } from '@opentrons/components' -import { i18n } from '../../localization' import { resetScrollElements } from '../../ui/steps/utils' import { Portal } from '../portals/MainPageModalPortal' import { useBlockingHint } from '../Hints/useBlockingHint' @@ -86,18 +85,20 @@ function getWarningContent({ gripperWithoutStep, fixtureWithoutStep, }: MissingContent): WarningContent | null { + const { t } = useTranslation(['alert', 'modules']) + if (noCommands) { return { content: ( <> -

{i18n.t('alert.export_warnings.no_commands.body1')}

+

{t('export_warnings.no_commands.body1')}

- {i18n.t('alert.export_warnings.no_commands.body2')} + {t('export_warnings.no_commands.body2')} here.

), - heading: i18n.t('alert.export_warnings.no_commands.heading'), + heading: t('export_warnings.no_commands.heading'), } } @@ -105,11 +106,11 @@ function getWarningContent({ return { content: ( <> -

{i18n.t('alert.export_warnings.unused_gripper.body1')}

-

{i18n.t('alert.export_warnings.unused_gripper.body2')}

+

{t('export_warnings.unused_gripper.body1')}

+

{t('export_warnings.unused_gripper.body2')}

), - heading: i18n.t('alert.export_warnings.unused_gripper.heading'), + heading: t('export_warnings.unused_gripper.heading'), } } @@ -117,9 +118,7 @@ function getWarningContent({ .map(pipette => `${pipette.mount} ${pipette.spec.displayName}`) .join(' and ') const modulesDetails = modulesWithoutStep - .map(moduleOnDeck => - i18n.t(`modules.module_long_names.${moduleOnDeck.type}`) - ) + .map(moduleOnDeck => t(`modules:module_long_names.${moduleOnDeck.type}`)) .join(' and ') if (pipettesWithoutStep.length && modulesWithoutStep.length) { @@ -127,19 +126,15 @@ function getWarningContent({ content: ( <>

- {i18n.t('alert.export_warnings.unused_pipette_and_module.body1', { + {t('export_warnings.unused_pipette_and_module.body1', { modulesDetails, pipettesDetails, })}

-

- {i18n.t('alert.export_warnings.unused_pipette_and_module.body2')} -

+

{t('export_warnings.unused_pipette_and_module.body2')}

), - heading: i18n.t( - 'alert.export_warnings.unused_pipette_and_module.heading' - ), + heading: t('export_warnings.unused_pipette_and_module.heading'), } } @@ -148,14 +143,14 @@ function getWarningContent({ content: ( <>

- {i18n.t('alert.export_warnings.unused_pipette.body1', { + {t('export_warnings.unused_pipette.body1', { pipettesDetails, })}

-

{i18n.t('alert.export_warnings.unused_pipette.body2')}

+

{t('export_warnings.unused_pipette.body2')}

), - heading: i18n.t('alert.export_warnings.unused_pipette.heading'), + heading: t('export_warnings.unused_pipette.heading'), } } @@ -166,14 +161,14 @@ function getWarningContent({ content: ( <>

- {i18n.t(`alert.export_warnings.${moduleCase}.body1`, { + {t(`export_warnings.${moduleCase}.body1`, { modulesDetails, })}

-

{i18n.t(`alert.export_warnings.${moduleCase}.body2`)}

+

{t(`export_warnings.${moduleCase}.body2`)}

), - heading: i18n.t(`alert.export_warnings.${moduleCase}.heading`), + heading: t(`export_warnings.${moduleCase}.heading`), } } @@ -183,19 +178,19 @@ function getWarningContent({ (fixtureWithoutStep.trashBin && !fixtureWithoutStep.wasteChute) || (!fixtureWithoutStep.trashBin && fixtureWithoutStep.wasteChute) ? (

- {i18n.t('alert.export_warnings.unused_trash.body', { + {t('export_warnings.unused_trash.body', { name: fixtureWithoutStep.trashBin ? 'trash bin' : 'waste chute', })}

) : (

- {i18n.t('alert.export_warnings.unused_trash.body_both', { + {t('export_warnings.unused_trash.body_both', { trashName: 'trash bin', wasteName: 'waste chute', })}

), - heading: i18n.t('alert.export_warnings.unused_trash.heading'), + heading: t('export_warnings.unused_trash.heading'), } } @@ -204,19 +199,19 @@ function getWarningContent({ content: ( <>

- {i18n.t('alert.export_warnings.unused_staging_area.body1', { + {t('export_warnings.unused_staging_area.body1', { count: fixtureWithoutStep.stagingAreaSlots.length, slot: fixtureWithoutStep.stagingAreaSlots, })}

- {i18n.t('alert.export_warnings.unused_staging_area.body2', { + {t('export_warnings.unused_staging_area.body2', { count: fixtureWithoutStep.stagingAreaSlots.length, })}

), - heading: i18n.t('alert.export_warnings.unused_staging_area.heading'), + heading: t('export_warnings.unused_staging_area.heading'), } } diff --git a/protocol-designer/src/components/FileSidebar/index.ts b/protocol-designer/src/components/FileSidebar/index.ts index c640b4a78c9..c27fc8a2fb8 100644 --- a/protocol-designer/src/components/FileSidebar/index.ts +++ b/protocol-designer/src/components/FileSidebar/index.ts @@ -1,5 +1,5 @@ import { connect } from 'react-redux' -import { i18n } from '../../localization' +import { useTranslation } from 'react-i18next' import { actions, selectors } from '../../navigation' import { selectors as fileDataSelectors } from '../../file-data' import { selectors as stepFormSelectors } from '../../step-forms' @@ -41,6 +41,7 @@ function mapStateToProps(state: BaseState): SP { const initialDeckSetup = stepFormSelectors.getInitialDeckSetup(state) const robotType = getRobotType(state) const additionalEquipment = getAdditionalEquipment(state) + const { t } = useTranslation('alert') return { canDownload, @@ -76,10 +77,7 @@ function mergeProps( const { dispatch } = dispatchProps return { loadFile: fileChangeEvent => { - if ( - !_hasUnsavedChanges || - window.confirm(i18n.t('alert.window.confirm_import')) - ) { + if (!_hasUnsavedChanges || window.confirm(t('window.confirm_import'))) { dispatch(loadFileActions.loadProtocolFile(fileChangeEvent)) } }, diff --git a/protocol-designer/src/components/Hints/index.tsx b/protocol-designer/src/components/Hints/index.tsx index ff93427d71f..cbf100d3358 100644 --- a/protocol-designer/src/components/Hints/index.tsx +++ b/protocol-designer/src/components/Hints/index.tsx @@ -7,7 +7,6 @@ import { OutlineButton, Text, } from '@opentrons/components' -import { i18n } from '../../localization' import { actions as stepsActions } from '../../ui/steps' import { TerminalItemId } from '../../steplist' import { actions, selectors, HintKey } from '../../tutorial' @@ -17,8 +16,10 @@ import EXAMPLE_ADD_LIQUIDS_IMAGE from '../../images/example_add_liquids.png' import EXAMPLE_WATCH_LIQUIDS_MOVE_IMAGE from '../../images/example_watch_liquids_move.png' import EXAMPLE_BATCH_EDIT_IMAGE from '../../images/announcements/multi_select.gif' import { BaseState, ThunkDispatch } from '../../types' +import { useTranslation } from 'react-i18next' interface SP { + t: any hintKey?: HintKey | null } interface DP { @@ -58,8 +59,10 @@ class HintsComponent extends React.Component { return ( <>
- {i18n.t('alert.hint.add_liquids_and_labware.summary', { - deck_setup_step: i18n.t('nav.terminal_item.__initial_setup__'), + {this.props.t('hint.add_liquids_and_labware.summary', { + deck_setup_step: this.props.t( + 'nav:terminal_item.__initial_setup__' + ), })}
@@ -67,7 +70,7 @@ class HintsComponent extends React.Component {
Step 1: - {i18n.t('alert.hint.add_liquids_and_labware.step1')} + {this.props.t('hint.add_liquids_and_labware.step1')}
@@ -77,7 +80,7 @@ class HintsComponent extends React.Component {
Step 2: - {i18n.t('alert.hint.add_liquids_and_labware.step2')} + {this.props.t('hint.add_liquids_and_labware.step2')}
@@ -87,31 +90,33 @@ class HintsComponent extends React.Component { case 'deck_setup_explanation': return ( <> -

{i18n.t(`alert.hint.${hintKey}.body1`)}

-

{i18n.t(`alert.hint.${hintKey}.body2`)}

-

{i18n.t(`alert.hint.${hintKey}.body3`)}

+

{this.props.t(`hint.${hintKey}.body1`)}

+

{this.props.t(`hint.${hintKey}.body2`)}

+

{this.props.t(`hint.${hintKey}.body3`)}

) case 'module_without_labware': return ( <> -

{i18n.t(`alert.hint.${hintKey}.body`)}

+

{this.props.t(`alert:hint.${hintKey}.body`)}

) case 'thermocycler_lid_passive_cooling': return ( <>

- {i18n.t(`alert.hint.${hintKey}.body1a`)} - {i18n.t(`alert.hint.${hintKey}.strong_body1`)} - {i18n.t(`alert.hint.${hintKey}.body1b`)} + {this.props.t(`alert:hint.${hintKey}.body1a`)} + + {this.props.t(`alert:hint.${hintKey}.strong_body1`)} + + {this.props.t(`alert:hint.${hintKey}.body1b`)}

  1. - {i18n.t(`alert.hint.${hintKey}.li1`)} + {this.props.t(`alert:hint.${hintKey}.li1`)}
  2. - {i18n.t(`alert.hint.${hintKey}.li2`)} + {this.props.t(`alert:hint.${hintKey}.li2`)}
@@ -123,33 +128,33 @@ class HintsComponent extends React.Component { -

{i18n.t(`alert.hint.${hintKey}.body1`)}

+

{this.props.t(`alert:hint.${hintKey}.body1`)}

- {i18n.t(`alert.hint.${hintKey}.body2`)} + {this.props.t(`alert:hint.${hintKey}.body2`)}

  1. - {i18n.t(`alert.hint.${hintKey}.li1a`)} + {this.props.t(`alert:hint.${hintKey}.li1a`)} - {i18n.t(`alert.hint.${hintKey}.strong_li1`)} + {this.props.t(`alert:hint.${hintKey}.strong_li1`)} - {i18n.t(`alert.hint.${hintKey}.li1b`)} + {this.props.t(`alert:hint.${hintKey}.li1b`)}
  2. - {i18n.t(`alert.hint.${hintKey}.li2a`)} + {this.props.t(`alert:hint.${hintKey}.li2a`)} - {i18n.t(`alert.hint.${hintKey}.strong_li2`)} + {this.props.t(`alert:hint.${hintKey}.strong_li2`)} - {i18n.t(`alert.hint.${hintKey}.li2b`)} + {this.props.t(`alert:hint.${hintKey}.li2b`)}

- {i18n.t(`alert.hint.${hintKey}.body3a`)}
- {i18n.t(`alert.hint.${hintKey}.body3b`)} + {this.props.t(`alert:hint.${hintKey}.body3a`)}
+ {this.props.t(`alert:hint.${hintKey}.body3b`)}

- {i18n.t(`alert.hint.${hintKey}.body4a`)}
- {i18n.t(`alert.hint.${hintKey}.body4b`)} + {this.props.t(`alert:hint.${hintKey}.body4a`)}
+ {this.props.t(`alert:hint.${hintKey}.body4b`)}

@@ -157,7 +162,7 @@ class HintsComponent extends React.Component { case 'waste_chute_warning': return ( - {i18n.t(`alert.hint.${hintKey}.body1`)} + {this.props.t(`hint.${hintKey}.body1`)} ) default: @@ -169,7 +174,7 @@ class HintsComponent extends React.Component { const { hintKey } = this.props if (!hintKey) return null - const headingText = i18n.t(`alert.hint.${hintKey}.title`) + const headingText = this.props.t(`hint.${hintKey}.title`) const hintIsAlert = HINT_IS_ALERT.includes(hintKey) return ( @@ -183,7 +188,7 @@ class HintsComponent extends React.Component {
@@ -191,7 +196,7 @@ class HintsComponent extends React.Component { className={styles.ok_button} onClick={this.makeHandleCloseClick(hintKey)} > - {i18n.t('button.ok')} + {this.props.t('button:ok')}
@@ -200,9 +205,13 @@ class HintsComponent extends React.Component { } } -const mapStateToProps = (state: BaseState): SP => ({ - hintKey: selectors.getHint(state), -}) +const mapStateToProps = (state: BaseState): SP => { + const { t } = useTranslation(['alert', 'nav', 'button']) + return { + hintKey: selectors.getHint(state), + t: t, + } +} const mapDispatchToProps = (dispatch: ThunkDispatch): DP => ({ removeHint: (hintKey, rememberDismissal) => dispatch(actions.removeHint(hintKey, rememberDismissal)), diff --git a/protocol-designer/src/components/Hints/useBlockingHint.tsx b/protocol-designer/src/components/Hints/useBlockingHint.tsx index 036328914e2..5301f27f92c 100644 --- a/protocol-designer/src/components/Hints/useBlockingHint.tsx +++ b/protocol-designer/src/components/Hints/useBlockingHint.tsx @@ -2,11 +2,11 @@ // Instances of BlockingHint need to be individually placed by whatever component // is controlling the flow that this modal will block, via useBlockingHint. import * as React from 'react' +import { useTranslation } from 'react-i18next' import { useDispatch, useSelector } from 'react-redux' import { actions, selectors, HintKey } from '../../tutorial' import { ContinueModal, DeprecatedCheckboxField } from '@opentrons/components' import { Portal } from '../portals/MainPageModalPortal' -import { i18n } from '../../localization' import styles from './hints.css' export interface HintProps { @@ -18,6 +18,7 @@ export interface HintProps { // This component handles the checkbox and dispatching `removeHint` action on continue/cancel export const BlockingHint = (props: HintProps): JSX.Element => { + const { t } = useTranslation('alert') const { hintKey, handleCancel, handleContinue } = props const dispatch = useDispatch() @@ -43,7 +44,7 @@ export const BlockingHint = (props: HintProps): JSX.Element => { @@ -51,7 +52,7 @@ export const BlockingHint = (props: HintProps): JSX.Element => {
diff --git a/protocol-designer/src/components/IngredientsList/LabwareDetailsCard/LabwareDetailsCard.tsx b/protocol-designer/src/components/IngredientsList/LabwareDetailsCard/LabwareDetailsCard.tsx index e6a473db3c4..f71634702c8 100644 --- a/protocol-designer/src/components/IngredientsList/LabwareDetailsCard/LabwareDetailsCard.tsx +++ b/protocol-designer/src/components/IngredientsList/LabwareDetailsCard/LabwareDetailsCard.tsx @@ -1,6 +1,6 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import cx from 'classnames' -import { i18n } from '../../../localization' import { PDTitledList, PDListItem } from '../../lists' import { EditableTextField } from '../../EditableTextField' import styles from './labwareDetailsCard.css' @@ -12,12 +12,13 @@ export interface Props { } export function LabwareDetailsCard(props: Props): JSX.Element { + const { t } = useTranslation('form') return (
- {i18n.t('form.generic.labware_type')} + {t('generic.labware_type')} {props.labwareDefDisplayName} @@ -27,7 +28,7 @@ export function LabwareDetailsCard(props: Props): JSX.Element {
- {i18n.t('form.generic.nickname')} + {t('generic.nickname')} { groupId, labwareWellContents, } = props - + const { t } = useTranslation(['card', 'application']) const showName = ingredGroup.serialize const [expanded, setExpanded] = React.useState(true) @@ -58,7 +58,7 @@ const LiquidGroupCard = (props: LiquidGroupCardProps): JSX.Element | null => { ingredGroup.name != null ? truncateString(ingredGroup.name, 25) : null return ( { description={} > - {i18n.t('card.well')} - {i18n.t('application.units.microliter')} - {showName && {i18n.t('card.name')}} + {t('well')} + {t('application:units.microliter')} + {showName && {t('name')}} @@ -125,13 +125,11 @@ function IngredIndividual(props: IndividProps): JSX.Element { groupId, removeWellsContents, } = props - + const { t } = useTranslation('application') return ( {wellName} - - {volume ? volume + ` ${i18n.t('application.units.microliter')}` : '-'} - + {volume ? volume + ` ${t('units.microliter')}` : '-'} {name && {name}} {canDelete && ( + {Object.keys(liquidGroupsById).map(groupIdForCard => ( diff --git a/protocol-designer/src/components/LabwareSelectionModal/LabwareItem.tsx b/protocol-designer/src/components/LabwareSelectionModal/LabwareItem.tsx index 593502bc209..47a3a4b82ac 100644 --- a/protocol-designer/src/components/LabwareSelectionModal/LabwareItem.tsx +++ b/protocol-designer/src/components/LabwareSelectionModal/LabwareItem.tsx @@ -1,6 +1,6 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import cx from 'classnames' -import { i18n } from '../../localization' import { Icon, IconName } from '@opentrons/components' import { PDListItem } from '../lists' import styles from './styles.css' @@ -31,7 +31,7 @@ export function LabwareItem(props: Props): JSX.Element { onMouseEnter, selectLabware, } = props - + const { t } = useTranslation('modal') const displayName = getLabwareDisplayName(labwareDef) const labwareURI = getLabwareDefURI(labwareDef) const labwareLoadName = labwareDef.parameters.loadName @@ -61,7 +61,7 @@ export function LabwareItem(props: Props): JSX.Element { href={`${LABWARE_LIBRARY_PAGE_PATH}/${labwareLoadName}`} onClick={e => e.stopPropagation()} > - {i18n.t('modal.labware_selection.view_measurements')} + {t('labware_selection.view_measurements')} ) : null} diff --git a/protocol-designer/src/components/LabwareSelectionModal/LabwarePreview.tsx b/protocol-designer/src/components/LabwareSelectionModal/LabwarePreview.tsx index d215fd807c8..2f89d6efde1 100644 --- a/protocol-designer/src/components/LabwareSelectionModal/LabwarePreview.tsx +++ b/protocol-designer/src/components/LabwareSelectionModal/LabwarePreview.tsx @@ -1,5 +1,6 @@ import * as React from 'react' import reduce from 'lodash/reduce' +import { useTranslation } from 'react-i18next' import { Icon, LabwareRender, @@ -11,7 +12,6 @@ import { getLabwareDefIsStandard, LabwareDefinition2, } from '@opentrons/shared-data' -import { i18n } from '../../localization' import styles from './styles.css' interface Props { @@ -25,6 +25,7 @@ interface Props { export const LabwarePreview = (props: Props): JSX.Element | null => { const { labwareDef, moduleCompatibility } = props + const { t } = useTranslation(['modal', 'application']) if (!labwareDef) return null const maxVolumes = reduce( labwareDef.wells, @@ -32,7 +33,7 @@ export const LabwarePreview = (props: Props): JSX.Element | null => { new Set() ) const formattedVolumes = Array.from(maxVolumes) - .map(vol => `${vol}${i18n.t('application.units.microliter')}`) + .map(vol => `${vol}${t('application:units.microliter')}`) .join(', ') // NOTE: this is a temporary magic value that positions the preview component @@ -51,9 +52,7 @@ export const LabwarePreview = (props: Props): JSX.Element | null => { {moduleCompatibility === 'recommended' ? ( ) : null} - {i18n.t( - `modal.labware_selection.module_compatibility.${moduleCompatibility}` - )} + {t(`labware_selection.module_compatibility.${moduleCompatibility}`)}
) : null}
@@ -67,17 +66,17 @@ export const LabwarePreview = (props: Props): JSX.Element | null => {
{getLabwareDefIsStandard(labwareDef) && ( )}
diff --git a/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.tsx b/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.tsx index f886399a9f7..2491108d6e5 100644 --- a/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.tsx +++ b/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.tsx @@ -1,4 +1,5 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import startCase from 'lodash/startCase' import reduce from 'lodash/reduce' import { @@ -23,7 +24,6 @@ import { getModuleType, THERMOCYCLER_MODULE_V2, } from '@opentrons/shared-data' -import { i18n } from '../../localization' import { SPAN7_8_10_11_SLOT } from '../../constants' import { getLabwareIsCompatible as _getLabwareIsCompatible, @@ -141,6 +141,7 @@ export const LabwareSelectionModal = (props: Props): JSX.Element | null => { adapterLoadName, has96Channel, } = props + const { t } = useTranslation(['modules', 'modal', 'button', 'alert']) const defs = getOnlyLatestDefs() const moduleType = moduleModel != null ? getModuleType(moduleModel) : null const URIs = Object.keys(defs) @@ -160,7 +161,7 @@ export const LabwareSelectionModal = (props: Props): JSX.Element | null => { const blockingCustomLabwareHint = useBlockingHint({ enabled: enqueuedLabwareType !== null, hintKey: 'custom_labware_with_modules', - content:

{i18n.t(`alert.hint.custom_labware_with_modules.body`)}

, + content:

{t(`alert:hint.custom_labware_with_modules.body`)}

, handleCancel: () => setEnqueuedLabwareType(null), handleContinue: () => { setEnqueuedLabwareType(null) @@ -237,8 +238,8 @@ export const LabwareSelectionModal = (props: Props): JSX.Element | null => { ) const getTitleText = (): string => { if (isNextToHeaterShaker) { - return `Slot ${slot}, Labware to the side of ${i18n.t( - `modules.module_long_names.heaterShakerModuleType` + return `Slot ${slot}, Labware to the side of ${t( + `module_long_names.heaterShakerModuleType` )}` } if (adapterLoadName != null) { @@ -249,9 +250,9 @@ export const LabwareSelectionModal = (props: Props): JSX.Element | null => { return `Labware on top of the ${adapterDisplayName}` } if (parentSlot != null && moduleType != null) { - return `Slot ${ - parentSlot === SPAN7_8_10_11_SLOT ? '7' : parentSlot - }, ${i18n.t(`modules.module_long_names.${moduleType}`)} Labware` + return `Slot ${parentSlot === SPAN7_8_10_11_SLOT ? '7' : parentSlot}, ${t( + `module_long_names.${moduleType}` + )} Labware` } return `Slot ${slot} Labware` } @@ -356,10 +357,10 @@ export const LabwareSelectionModal = (props: Props): JSX.Element | null => { )} - {i18n.t( + {t( isNextToHeaterShaker - ? 'modal.labware_selection.heater_shaker_labware_filter' - : 'modal.labware_selection.recommended_labware_filter' + ? 'modal:labware_selection.heater_shaker_labware_filter' + : 'modal:labware_selection.recommended_labware_filter' )}{' '} { - {i18n.t('button.upload_custom_labware')} + {t('button:upload_custom_labware')} { @@ -504,7 +505,7 @@ export const LabwareSelectionModal = (props: Props): JSX.Element | null => { />
- {i18n.t('modal.labware_selection.creating_labware_defs')}{' '} + {t('modal:labware_selection.creating_labware_defs')}{' '} {/* TODO: Ian 2019-10-15 use LinkOut component once it's in components library, see Opentrons/opentrons#4229 */} { .
- - {i18n.t('button.close')} - + {t('button:close')}
) diff --git a/protocol-designer/src/components/LiquidPlacementForm/LiquidPlacementForm.tsx b/protocol-designer/src/components/LiquidPlacementForm/LiquidPlacementForm.tsx index bed3d18a7ec..cb8185efe24 100644 --- a/protocol-designer/src/components/LiquidPlacementForm/LiquidPlacementForm.tsx +++ b/protocol-designer/src/components/LiquidPlacementForm/LiquidPlacementForm.tsx @@ -11,7 +11,6 @@ import { DeprecatedPrimaryButton, Options, } from '@opentrons/components' -import { i18n } from '../../localization' import styles from './LiquidPlacementForm.css' import formStyles from '../forms/forms.css' import stepEditFormStyles from '../StepEditForm/StepEditForm.css' @@ -32,7 +31,7 @@ export interface Props { liquidSelectionOptions: Options selectedWellsMaxVolume: number showForm: boolean - + t: any cancelForm: () => unknown clearWells: (() => unknown | null) | null saveForm: (liquidPlacementFormValues: LiquidPlacementFormValues) => unknown @@ -58,21 +57,21 @@ export class LiquidPlacementForm extends React.Component { const { selectedWellsMaxVolume } = this.props return Yup.object().shape({ selectedLiquidId: Yup.string().required( - i18n.t('form.generic.error.required', { - name: i18n.t('form.liquid_placement.liquid'), + this.props.t('generic.error.required', { + name: this.props.t('liquid_placement.liquid'), }) ), volume: Yup.number() .nullable() .required( - i18n.t('form.generic.error.required', { - name: i18n.t('form.liquid_placement.volume'), + this.props.t('generic.error.required', { + name: this.props.t('liquid_placement.volume'), }) ) - .moreThan(0, i18n.t('form.generic.error.more_than_zero')) + .moreThan(0, this.props.t('generic.error.more_than_zero')) .max( selectedWellsMaxVolume, - i18n.t('form.liquid_placement.volume_exceeded', { + this.props.t('liquid_placement.volume_exceeded', { volume: selectedWellsMaxVolume, }) ), @@ -126,7 +125,7 @@ export class LiquidPlacementForm extends React.Component {
{ /> { disabled={!this.props.clearWells} onClick={this.handleClearWells} > - {i18n.t('button.clear_wells')} + {this.props.t('button:clear_wells')} - {i18n.t('button.cancel')} + {this.props.t('button:cancel')} - {i18n.t('button.save')} + {this.props.t('button:save')}
diff --git a/protocol-designer/src/components/LiquidPlacementForm/index.ts b/protocol-designer/src/components/LiquidPlacementForm/index.ts index a80df26a151..e3d4541510e 100644 --- a/protocol-designer/src/components/LiquidPlacementForm/index.ts +++ b/protocol-designer/src/components/LiquidPlacementForm/index.ts @@ -16,6 +16,7 @@ import { } from './LiquidPlacementForm' import { Dispatch } from 'redux' import { BaseState } from '../../types' +import { useTranslation } from 'react-i18next' type SP = Omit< LiquidPlacementFormProps & { _labwareId?: string | null @@ -27,7 +28,7 @@ type SP = Omit< function mapStateToProps(state: BaseState): SP { const selectedWells = getSelectedWells(state) - + const { t } = useTranslation(['form', 'button', 'application']) const _labwareId = labwareIngredSelectors.getSelectedLabwareId(state) const liquidLocations = labwareIngredSelectors.getLiquidsByLabwareId(state) @@ -55,6 +56,7 @@ function mapStateToProps(state: BaseState): SP { _labwareId, _selectedWells: Object.keys(selectedWells), _selectionHasLiquids, + t: t, } } diff --git a/protocol-designer/src/components/LiquidsPage/LiquidEditForm.tsx b/protocol-designer/src/components/LiquidsPage/LiquidEditForm.tsx index 64318438729..edbb0425f4b 100644 --- a/protocol-designer/src/components/LiquidsPage/LiquidEditForm.tsx +++ b/protocol-designer/src/components/LiquidsPage/LiquidEditForm.tsx @@ -1,8 +1,8 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' import { Field, Formik, FormikProps } from 'formik' import * as Yup from 'yup' -import { i18n } from '../../localization' import { swatchColors } from '../swatchColors' import { Card, @@ -81,7 +81,7 @@ export function LiquidEditForm(props: Props): JSX.Element { const selectedLiquid = useSelector(selectors.getSelectedLiquidGroupState) const nextGroupId = useSelector(selectors.getNextLiquidGroupId) const liquidId = selectedLiquid.liquidGroupId ?? nextGroupId - + const { t } = useTranslation(['form', 'button']) const initialValues: LiquidEditFormValues = { name: props.name || '', displayColor: props.displayColor ?? swatchColors(liquidId), @@ -118,11 +118,11 @@ export function LiquidEditForm(props: Props): JSX.Element {
- {i18n.t('form.liquid_edit.details')} + {t('liquid_edit.details')}
- +
- {i18n.t('form.liquid_edit.serialize_title')} + {t('liquid_edit.serialize_title')}

- {i18n.t('form.liquid_edit.serialize_explanation')} + {t('liquid_edit.serialize_explanation')}

@@ -184,10 +184,10 @@ export function LiquidEditForm(props: Props): JSX.Element { onClick={deleteLiquidGroup} disabled={!canDelete} > - {i18n.t('button.delete')} + {t('button:delete')} - {i18n.t('button.cancel')} + {t('button:cancel')} - {i18n.t('button.save')} + {t('button:save')}
diff --git a/protocol-designer/src/components/LiquidsSidebar/index.tsx b/protocol-designer/src/components/LiquidsSidebar/index.tsx index 83578c4022e..e36022ba3ba 100644 --- a/protocol-designer/src/components/LiquidsSidebar/index.tsx +++ b/protocol-designer/src/components/LiquidsSidebar/index.tsx @@ -1,6 +1,6 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import { connect } from 'react-redux' -import { i18n } from '../../localization' import { DeprecatedPrimaryButton, SidePanel, @@ -16,7 +16,6 @@ import * as labwareIngredActions from '../../labware-ingred/actions' import { BaseState, ThunkDispatch } from '../../types' import styles from './styles.css' - interface SP { liquids: OrderedLiquids selectedLiquid?: string | null @@ -31,6 +30,7 @@ type Props = SP & DP function LiquidsSidebarComponent(props: Props): JSX.Element { const { liquids, selectedLiquid, createNewLiquid, selectLiquid } = props + const { t } = useTranslation('button') return ( {liquids.map(({ ingredientId, name, displayColor }) => ( @@ -55,7 +55,7 @@ function LiquidsSidebarComponent(props: Props): JSX.Element { ))}
- {i18n.t('button.new_liquid')} + {t('new_liquid')}
diff --git a/protocol-designer/src/components/SettingsPage/FeatureFlagCard/FeatureFlagCard.tsx b/protocol-designer/src/components/SettingsPage/FeatureFlagCard/FeatureFlagCard.tsx index fab5720c11e..755027ee57e 100644 --- a/protocol-designer/src/components/SettingsPage/FeatureFlagCard/FeatureFlagCard.tsx +++ b/protocol-designer/src/components/SettingsPage/FeatureFlagCard/FeatureFlagCard.tsx @@ -1,7 +1,7 @@ -import sortBy from 'lodash/sortBy' import * as React from 'react' +import { useTranslation } from 'react-i18next' +import sortBy from 'lodash/sortBy' import { ContinueModal, Card, ToggleButton } from '@opentrons/components' -import { i18n } from '../../../localization' import { resetScrollElements } from '../../../ui/steps/utils' import { Portal } from '../../portals/MainPageModalPortal' import styles from '../SettingsPage.css' @@ -17,6 +17,7 @@ export const FeatureFlagCard = (props: Props): JSX.Element => { const [modalFlagName, setModalFlagName] = React.useState( null ) + const { t } = useTranslation(['modal', 'card', 'feature_flags']) const prereleaseModeEnabled = props.flags.PRERELEASE_MODE === true @@ -35,20 +36,18 @@ export const FeatureFlagCard = (props: Props): JSX.Element => { const RICH_DESCRIPTIONS: Partial> = { OT_PD_ALLOW_ALL_TIPRACKS: ( <> -

{i18n.t(`feature_flags.${flag}.description`)}

+

{t(`feature_flags:${flag}.description`)}

), OT_PD_DISABLE_MODULE_RESTRICTIONS: ( <> -

{i18n.t(`feature_flags.${flag}.description_1`)}

-

{i18n.t(`feature_flags.${flag}.description_2`)}

+

{t(`feature_flags:${flag}.description_1`)}

+

{t(`feature_flags:${flag}.description_2`)}

), } return ( - RICH_DESCRIPTIONS[flag] || ( -

{i18n.t(`feature_flags.${flag}.description`)}

- ) + RICH_DESCRIPTIONS[flag] ||

{t(`feature_flags:${flag}.description`)}

) } @@ -56,7 +55,7 @@ export const FeatureFlagCard = (props: Props): JSX.Element => {

- {i18n.t(`feature_flags.${flagName}.title`)} + {t(`feature_flags:${flagName}.title`)}

{ setModalFlagName(null)} onContinueClick={() => { @@ -108,25 +107,21 @@ export const FeatureFlagCard = (props: Props): JSX.Element => { }} >

- {i18n.t( - `modal.experimental_feature_warning.${flagSwitchDirection}.body1` - )} + {t(`experimental_feature_warning.${flagSwitchDirection}.body1`)}

- {i18n.t( - `modal.experimental_feature_warning.${flagSwitchDirection}.body2` - )} + {t(`experimental_feature_warning.${flagSwitchDirection}.body2`)}

)} - +
{userFacingFlagRows.length > 0 ? userFacingFlagRows : noFlagsFallback}
{prereleaseModeEnabled && ( - +
{prereleaseFlagRows}
)} diff --git a/protocol-designer/src/components/SettingsPage/SettingsApp.tsx b/protocol-designer/src/components/SettingsPage/SettingsApp.tsx index 0816a5b0832..9f6f03c3253 100644 --- a/protocol-designer/src/components/SettingsPage/SettingsApp.tsx +++ b/protocol-designer/src/components/SettingsPage/SettingsApp.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { connect } from 'react-redux' -import { i18n } from '../../localization' +import { useTranslation } from 'react-i18next' import { Card, OutlineButton, @@ -39,15 +39,16 @@ function SettingsAppComponent(props: Props): JSX.Element { restoreHints, toggleOptedIn, } = props + const { t } = useTranslation(['card', 'application', 'button']) return ( <>
- +
{/* TODO: BC 2019-02-26 add release notes link here, when there are release notes */} @@ -56,30 +57,28 @@ function SettingsAppComponent(props: Props): JSX.Element {
- +
- {i18n.t('card.body.restore_hints')} + {t('body.restore_hints')} {canClearHintDismissals - ? i18n.t('button.restore') - : i18n.t('button.restored')} + ? t('button:restore') + : t('button:restored')}
- +
-

- {i18n.t('card.toggle.share_session')} -

+

{t('toggle.share_session')}

- {i18n.t('card.body.reason_for_collecting_data')}{' '} - {i18n.t('card.body.data_collected_is_internal')}. + {t('body.reason_for_collecting_data')}{' '} + {t('body.data_collected_is_internal')}.

diff --git a/protocol-designer/src/components/SettingsPage/SettingsSidebar.tsx b/protocol-designer/src/components/SettingsPage/SettingsSidebar.tsx index ccfc06cc34e..e1546e78dd4 100644 --- a/protocol-designer/src/components/SettingsPage/SettingsSidebar.tsx +++ b/protocol-designer/src/components/SettingsPage/SettingsSidebar.tsx @@ -1,43 +1,21 @@ import * as React from 'react' +import { useSelector } from 'react-redux' +import { useTranslation } from 'react-i18next' import { SidePanel } from '@opentrons/components' -import { connect } from 'react-redux' - -import { BaseState, ThunkDispatch } from '../../types' -import { actions, selectors, Page } from '../../navigation' -import { i18n } from '../../localization' +import { selectors } from '../../navigation' import { PDTitledList } from '../lists' import styles from './SettingsPage.css' -interface SP { - currentPage: Page -} -interface DP { - makeNavigateToPage: (page: Page) => () => unknown +export const SettingsSidebar = (): JSX.Element => { + const currentPage = useSelector(selectors.getCurrentPage) + const { t } = useTranslation('nav') + return ( + + + + ) } -type Props = SP & DP - -const SettingsSidebarComponent = (props: Props): JSX.Element => ( - - - {/* */} - -) - -const STP = (state: BaseState): SP => ({ - currentPage: selectors.getCurrentPage(state), -}) - -const DTP = (dispatch: ThunkDispatch): DP => ({ - makeNavigateToPage: (pageName: Page) => () => - dispatch(actions.navigateToPage(pageName)), -}) - -export const SettingsSidebar = connect(STP, DTP)(SettingsSidebarComponent) diff --git a/protocol-designer/src/components/StepEditForm/ButtonRow/index.tsx b/protocol-designer/src/components/StepEditForm/ButtonRow/index.tsx index 6ea1d67b7ac..bcf1187bcba 100644 --- a/protocol-designer/src/components/StepEditForm/ButtonRow/index.tsx +++ b/protocol-designer/src/components/StepEditForm/ButtonRow/index.tsx @@ -1,7 +1,7 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import cx from 'classnames' import { OutlineButton, DeprecatedPrimaryButton } from '@opentrons/components' -import { i18n } from '../../../localization' import modalStyles from '../../modals/modal.css' import styles from './styles.css' @@ -22,18 +22,18 @@ export const ButtonRow = (props: ButtonRowProps): JSX.Element => { handleSave, canSave, } = props - + const { t } = useTranslation('button') return (
- {i18n.t('button.delete')} + {t('delete')} - {i18n.t('button.notes')} + {t('notes')}
@@ -41,14 +41,14 @@ export const ButtonRow = (props: ButtonRowProps): JSX.Element => { className={styles.form_button} onClick={handleClose} > - {i18n.t('button.close')} + {t('close')} - {i18n.t('button.save')} + {t('save')}
diff --git a/protocol-designer/src/components/StepEditForm/fields/ChangeTipField/index.tsx b/protocol-designer/src/components/StepEditForm/fields/ChangeTipField/index.tsx index 758f6838a4d..44dfa8d625b 100644 --- a/protocol-designer/src/components/StepEditForm/fields/ChangeTipField/index.tsx +++ b/protocol-designer/src/components/StepEditForm/fields/ChangeTipField/index.tsx @@ -1,4 +1,5 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import { FormGroup, SelectField, @@ -6,7 +7,6 @@ import { useHoverTooltip, TOOLTIP_FIXED, } from '@opentrons/components' -import { i18n } from '../../../../localization' import { getDisabledChangeTipOptions, DisabledChangeTipArgs, @@ -34,7 +34,7 @@ export const ChangeTipField = (props: Props): JSX.Element => { updateValue, value, } = props - + const { t } = useTranslation('form') const disabledOptions = getDisabledChangeTipOptions({ aspirateWells, dispenseWells, @@ -49,7 +49,7 @@ export const ChangeTipField = (props: Props): JSX.Element => { return ( { const { value } = props + const { t } = useTranslation('form') const [targetProps, tooltipProps] = useHoverTooltip({ placement: 'bottom-start', strategy: TOOLTIP_FIXED, @@ -78,12 +79,10 @@ const ChangeTipOptionLabel = (props: LabelProps): JSX.Element => { return ( <>
- {i18n.t(`form.step_edit_form.field.change_tip.option.${value}`)} + {t(`step_edit_form.field.change_tip.option.${value}`)}
- {i18n.t( - `form.step_edit_form.field.change_tip.option_tooltip.${value}` - )} + {t(`step_edit_form.field.change_tip.option_tooltip.${value}`)}
diff --git a/protocol-designer/src/components/StepEditForm/fields/DropTipField/index.tsx b/protocol-designer/src/components/StepEditForm/fields/DropTipField/index.tsx index 15cdd7e887d..0448d348430 100644 --- a/protocol-designer/src/components/StepEditForm/fields/DropTipField/index.tsx +++ b/protocol-designer/src/components/StepEditForm/fields/DropTipField/index.tsx @@ -1,7 +1,7 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' import { DropdownField, DropdownOption, FormGroup } from '@opentrons/components' -import { i18n } from '../../../../localization' import { getAdditionalEquipmentEntities } from '../../../../step-forms/selectors' import { StepFormDropdown } from '../StepFormDropdownField' import styles from '../../StepEditForm.css' @@ -16,6 +16,7 @@ export function DropTipField( onFieldFocus, updateValue, } = props + const { t } = useTranslation('form') const additionalEquipment = useSelector(getAdditionalEquipmentEntities) const wasteChute = Object.values(additionalEquipment).find( aE => aE.name === 'wasteChute' @@ -43,7 +44,7 @@ export function DropTipField( }, [dropdownItem]) return ( { name, pipetteDisplayName, } = props - const { t } = useTranslation('form') + const { t } = useTranslation(['form', 'application']) const DEFAULT_LABEL = t('step_edit_form.field.flow_rate.label') const initialState: State = { @@ -142,7 +141,7 @@ export const FlowRateInput = (props: FlowRateInputProps): JSX.Element => { isIndeterminate={isIndeterminate && modalFlowRate === null} name={`${name}_customFlowRate`} onChange={handleChangeNumber} - units={i18n.t('application.units.microliterPerSec')} + units={t('application:units.microliterPerSec')} value={`${modalFlowRate || ''}`} /> ) @@ -181,8 +180,8 @@ export const FlowRateInput = (props: FlowRateInputProps): JSX.Element => { onChange={handleChangeRadio} options={[ { - name: `${defaultFlowRate || '?'} ${i18n.t( - 'application.units.microliterPerSec' + name: `${defaultFlowRate || '?'} ${t( + 'application:units.microliterPerSec' )} (default)`, value: 'default', }, @@ -207,7 +206,7 @@ export const FlowRateInput = (props: FlowRateInputProps): JSX.Element => { name={name} onClick={openModal} readOnly - units={i18n.t('application.units.microliterPerSec')} + units={t('application:units.microliterPerSec')} value={props.value ? String(props.value) : 'default'} /> diff --git a/protocol-designer/src/components/StepEditForm/fields/LabwareLocationField/index.tsx b/protocol-designer/src/components/StepEditForm/fields/LabwareLocationField/index.tsx index 8dedd756389..072f7fa5e02 100644 --- a/protocol-designer/src/components/StepEditForm/fields/LabwareLocationField/index.tsx +++ b/protocol-designer/src/components/StepEditForm/fields/LabwareLocationField/index.tsx @@ -1,10 +1,10 @@ import * as React from 'react' import { useSelector } from 'react-redux' +import { useTranslation } from 'react-i18next' import { getModuleDisplayName, WASTE_CHUTE_CUTOUT, } from '@opentrons/shared-data' -import { i18n } from '../../../../localization' import { getAdditionalEquipmentEntities, getLabwareEntities, @@ -22,6 +22,7 @@ export function LabwareLocationField( useGripper: boolean } & { canSave: boolean } & { labware: string } ): JSX.Element { + const { t } = useTranslation('form') const { labware, useGripper, value } = props const labwareEntities = useSelector(getLabwareEntities) const robotState = useSelector(getRobotStateAtActiveItem) @@ -79,10 +80,10 @@ export function LabwareLocationField( {...props} errorToShow={ !props.canSave && bothFieldsSelected - ? i18n.t( - 'form.step_edit_form.labwareLabel.errors.labwareSlotIncompatible', - { labwareName: labwareDisplayName, slot: locationString } - ) + ? t('step_edit_form.labwareLabel.errors.labwareSlotIncompatible', { + labwareName: labwareDisplayName, + slot: locationString, + }) : undefined } options={unoccupiedLabwareLocationsOptions} diff --git a/protocol-designer/src/components/StepEditForm/fields/PathField/Path.tsx b/protocol-designer/src/components/StepEditForm/fields/PathField/Path.tsx index d8108997074..6990ffc44f3 100644 --- a/protocol-designer/src/components/StepEditForm/fields/PathField/Path.tsx +++ b/protocol-designer/src/components/StepEditForm/fields/PathField/Path.tsx @@ -1,7 +1,7 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import cx from 'classnames' import { FormGroup, Tooltip, useHoverTooltip } from '@opentrons/components' -import { i18n } from '../../../../localization' import SINGLE_IMAGE from '../../../../images/path_single_transfers.svg' import MULTI_DISPENSE_IMAGE from '../../../../images/path_multi_dispense.svg' import MULTI_ASPIRATE_IMAGE from '../../../../images/path_multi_aspirate.svg' @@ -57,11 +57,11 @@ const PathButton = (buttonProps: ButtonProps): JSX.Element => { subtitle, } = buttonProps const [targetProps, tooltipProps] = useHoverTooltip() - + const { t } = useTranslation('form') const tooltip = (
- {i18n.t(`form.step_edit_form.field.path.title.${path}`)} + {t(`step_edit_form.field.path.title.${path}`)}
@@ -111,13 +111,14 @@ interface WrapperProps { targetProps: UseHoverTooltipTargetProps } -const Wrapper = (props: WrapperProps): JSX.Element => - props.isTouchTipField || props.isDelayPositionField ? ( +const Wrapper = (props: WrapperProps): JSX.Element => { + const { t } = useTranslation('form') + return props.isTouchTipField || props.isDelayPositionField ? (
{props.children}
) : ( @@ -125,7 +126,7 @@ const Wrapper = (props: WrapperProps): JSX.Element => ) - +} const mapSTP = (state: BaseState, ownProps: OP): SP => { const { labwareId, value } = ownProps diff --git a/protocol-designer/src/components/labware/BrowseLabwareModal.tsx b/protocol-designer/src/components/labware/BrowseLabwareModal.tsx index 20422d8728c..d76f4c90a03 100644 --- a/protocol-designer/src/components/labware/BrowseLabwareModal.tsx +++ b/protocol-designer/src/components/labware/BrowseLabwareModal.tsx @@ -1,5 +1,4 @@ import assert from 'assert' -import { i18n } from '../../localization' import * as React from 'react' import cx from 'classnames' import { connect } from 'react-redux' @@ -19,6 +18,7 @@ import { LabwareDefinition2 } from '@opentrons/shared-data' import modalStyles from '../modals/modal.css' import styles from './labware.css' +import { useTranslation } from 'react-i18next' interface SP { definition?: LabwareDefinition2 | null @@ -34,6 +34,7 @@ type Props = SP & DP const BrowseLabwareModalComponent = (props: Props): JSX.Element | null => { const { drillUp, definition, ingredNames, wellContents } = props + const { t } = useTranslation('modal') if (!definition) { assert(definition, 'BrowseLabwareModal expected definition') return null @@ -54,7 +55,7 @@ const BrowseLabwareModalComponent = (props: Props): JSX.Element | null => { wellContents={wellContents} />
- {i18n.t('modal.browse_labware.instructions')} + {t('browse_labware.instructions')}
) diff --git a/protocol-designer/src/components/modules/AdditionalItemsRow.tsx b/protocol-designer/src/components/modules/AdditionalItemsRow.tsx index dc5b0510000..aa13214afef 100644 --- a/protocol-designer/src/components/modules/AdditionalItemsRow.tsx +++ b/protocol-designer/src/components/modules/AdditionalItemsRow.tsx @@ -1,4 +1,5 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import styled from 'styled-components' import { getCutoutDisplayName, @@ -17,7 +18,6 @@ import { TYPOGRAPHY, DIRECTION_ROW, } from '@opentrons/components' -import { i18n } from '../../localization' import gripperImage from '../../images/flex_gripper.png' import wasteChuteImage from '../../images/waste_chute.png' import trashBinImage from '../../images/flex_trash_bin.png' @@ -49,6 +49,7 @@ export function AdditionalItemsRow( trashBinId, hasWasteChute, } = props + const { t } = useTranslation(['modules', 'shared', 'tooltip']) const [targetProps, tooltipProps] = useHoverTooltip() const [trashModal, openTrashModal] = React.useState(false) const addTrash = name !== 'gripper' && !isEquipmentAdded @@ -76,13 +77,13 @@ export function AdditionalItemsRow( ) : null}

- {i18n.t(`modules.additional_equipment_display_names.${name}`)} + {t(`additional_equipment_display_names.${name}`)}

) : null}
@@ -131,7 +132,7 @@ export function AdditionalItemsRow( onClick={() => openTrashModal(true)} className={styles.module_button} > - {i18n.t('shared.edit')} + {t('shared:edit')} ) : null} openTrashModal(true) : handleAttachment } > - {isEquipmentAdded - ? i18n.t('shared.remove') - : i18n.t('shared.add')} + {isEquipmentAdded ? t('shared:remove') : t('shared:add')} {disabledRemoveButton ? ( @@ -158,7 +157,7 @@ export function AdditionalItemsRow( width="10rem" textAlign={TYPOGRAPHY.textAlignCenter} > - {i18n.t(`tooltip.disabled_cannot_delete_trash`)} + {t(`tooltip:disabled_cannot_delete_trash`)}
) : null} diff --git a/protocol-designer/src/components/modules/CrashInfoBox.tsx b/protocol-designer/src/components/modules/CrashInfoBox.tsx index 11663cb9225..ec4e61ceac4 100644 --- a/protocol-designer/src/components/modules/CrashInfoBox.tsx +++ b/protocol-designer/src/components/modules/CrashInfoBox.tsx @@ -1,6 +1,6 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import { Icon, SPACING_3 } from '@opentrons/components' -import { i18n } from '../../localization' import collisionImage from '../../images/modules/module_pipette_collision_warning.png' import { KnowledgeBaseLink } from '../KnowledgeBaseLink' import styles from './styles.css' @@ -20,31 +20,30 @@ type TempMagCollisonProps = Pick< > const HeaterShakerPipetteCollisions = (): JSX.Element | null => { + const { t } = useTranslation('alert') return ( <>
  • - 8-Channel {i18n.t(`alert.crash.pipettes_east_west`)}{' '} + 8-Channel {t(`crash.pipettes_east_west`)}{' '} Heater-Shaker Module GEN1.
  • - 8-Channel{' '} - {i18n.t(`alert.crash.pipettes_can_access_north_south`)}{' '} - Heater-Shaker Module GEN1{' '} - {i18n.t(`alert.crash.slot_has_tiprack`)} + 8-Channel {t(`crash.pipettes_can_access_north_south`)}{' '} + Heater-Shaker Module GEN1 {t(`crash.slot_has_tiprack`)}
  • ) } const TempMagCollisions = (props: TempMagCollisonProps): JSX.Element => { + const { t } = useTranslation('alert') const moduleMessage = getCrashableModulesCopy(props) || '' return (
  • 8-Channel GEN1{' '} - {i18n.t(`alert.crash.pipettes_cannot_access_north_south`)} {moduleMessage} - .{' '} + {t(`crash.pipettes_cannot_access_north_south`)} {moduleMessage}.{' '} - {i18n.t(`alert.crash.read_more_here`)} + {t(`crash.read_more_here`)}
  • ) @@ -79,14 +78,14 @@ const PipetteModuleCollisions = (props: Props): JSX.Element | null => { const ModuleLabwareCollisions = ( props: Pick ): JSX.Element | null => { + const { t } = useTranslation('alert') if (!props.showHeaterShakerLabwareCollisions) return null const title = 'Potential module-labware collisions' const body = (
  • - {i18n.t(`alert.crash.no_labware_over`)} 53 mm{' '} - {i18n.t(`alert.crash.labware_east_west`)}{' '} - Heater-Shaker Module GEN1{' '} - {i18n.t(`alert.crash.latch_collision`)}{' '} + {t(`crash.no_labware_over`)} 53 mm{' '} + {t(`crash.labware_east_west`)} Heater-Shaker Module GEN1{' '} + {t(`crash.latch_collision`)}{' '}
  • ) return @@ -94,11 +93,13 @@ const ModuleLabwareCollisions = ( const ModuleModuleCollisions = ( props: Pick ): JSX.Element | null => { + const { t } = useTranslation('alert') + if (!props.showHeaterShakerModuleCollisions) return null const title = 'Potential module-module collisions' const body = (
  • - {i18n.t(`alert.crash.modules_north_south`)}{' '} + {t(`crash.modules_north_south`)}{' '} Heater-Shaker Module GEN1.
  • ) diff --git a/protocol-designer/src/components/modules/ModuleRow.tsx b/protocol-designer/src/components/modules/ModuleRow.tsx index 073082878b3..068edeebcff 100644 --- a/protocol-designer/src/components/modules/ModuleRow.tsx +++ b/protocol-designer/src/components/modules/ModuleRow.tsx @@ -1,4 +1,5 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import { useDispatch } from 'react-redux' import upperFirst from 'lodash/upperFirst' import { @@ -16,7 +17,6 @@ import { FLEX_ROBOT_TYPE, THERMOCYCLER_MODULE_TYPE, } from '@opentrons/shared-data' -import { i18n } from '../../localization' import { actions as stepFormActions, ModuleOnDeck } from '../../step-forms' import { SPAN7_8_10_11_SLOT, @@ -44,6 +44,7 @@ export function ModuleRow(props: Props): JSX.Element { showCollisionWarnings, robotType, } = props + const { t } = useTranslation(['modules', 'tooltip']) const type: ModuleType = moduleOnDeck?.type || props.type const isFlex = robotType === FLEX_ROBOT_TYPE const model = moduleOnDeck?.model @@ -86,12 +87,12 @@ export function ModuleRow(props: Props): JSX.Element { // default module slot placement magnet = Slot1 temperature = Slot3 let collisionTooltipText = null if (collisionSlots && collisionSlots.includes('4')) { - collisionTooltipText = i18n.t( - `tooltip.edit_module_card.magnetic_module_collision` + collisionTooltipText = t( + `tooltip:edit_module_card.magnetic_module_collision` ) } else if (collisionSlots && collisionSlots.includes('6')) { - collisionTooltipText = i18n.t( - `tooltip.edit_module_card.temperature_module_collision` + collisionTooltipText = t( + `tooltip:edit_module_card.temperature_module_collision` ) } @@ -126,7 +127,7 @@ export function ModuleRow(props: Props): JSX.Element { color={C_DARK_GRAY} marginRight={SPACING.spacing4} /> - {i18n.t(`modules.module_display_names.${type}`)} + {t(`module_display_names.${type}`)}
    @@ -139,7 +140,7 @@ export function ModuleRow(props: Props): JSX.Element { {model && ( )}
    diff --git a/protocol-designer/src/components/modules/StagingAreasModal.tsx b/protocol-designer/src/components/modules/StagingAreasModal.tsx index c9991bcf3b3..7c9928d5444 100644 --- a/protocol-designer/src/components/modules/StagingAreasModal.tsx +++ b/protocol-designer/src/components/modules/StagingAreasModal.tsx @@ -1,4 +1,5 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import { useSelector, useDispatch } from 'react-redux' import { Form, Formik, useFormikContext } from 'formik' import { @@ -24,7 +25,6 @@ import { STAGING_AREA_RIGHT_SLOT_FIXTURE, } from '@opentrons/shared-data' import { getStagingAreaSlots } from '../../utils' -import { i18n } from '../../localization' import { createDeckFixture, deleteDeckFixture, @@ -41,6 +41,7 @@ export interface StagingAreasValues { const StagingAreasModalComponent = ( props: StagingAreasModalProps ): JSX.Element => { + const { t } = useTranslation(['button', 'alert']) const { onCloseClick, stagingAreas } = props const { values, setFieldValue } = useFormikContext() const initialDeckSetup = useSelector(getInitialDeckSetup) @@ -133,8 +134,8 @@ const StagingAreasModalComponent = ( {hasConflictedSlot ? ( @@ -155,11 +156,9 @@ const StagingAreasModalComponent = ( paddingBottom={SPACING.spacing32} gridGap={SPACING.spacing8} > - - {i18n.t('button.cancel')} - + {t('cancel')} - {i18n.t('button.save')} + {t('save')} @@ -175,6 +174,7 @@ export const StagingAreasModal = ( props: StagingAreasModalProps ): JSX.Element => { const { onCloseClick, stagingAreas } = props + const { t } = useTranslation('modules') const dispatch = useDispatch() const stagingAreaLocations = getStagingAreaSlots(stagingAreas) @@ -203,7 +203,7 @@ export const StagingAreasModal = ( - {i18n.t(`modules.additional_equipment_display_names.stagingAreas`)} + {t(`additional_equipment_display_names.stagingAreas`)} 0 const [stagingAreaModal, openStagingAreaModal] = React.useState( false @@ -48,15 +49,13 @@ export function StagingAreasRow(props: StagingAreasRowProps): JSX.Element { ) : null}

    - {i18n.t(`modules.additional_equipment_display_names.stagingAreas`)} + {t(`additional_equipment_display_names.stagingAreas`)}

    openStagingAreaModal(true)} className={styles.module_button} > - {i18n.t('shared.edit')} + {t('shared:edit')} ) : null} openStagingAreaModal(true) } > - {hasStagingAreas - ? i18n.t('shared.remove') - : i18n.t('shared.add')} + {hasStagingAreas ? t('shared:remove') : t('shared:add')} diff --git a/protocol-designer/src/components/modules/TrashModal.tsx b/protocol-designer/src/components/modules/TrashModal.tsx index 23c3d91ad2e..c919f224bb3 100644 --- a/protocol-designer/src/components/modules/TrashModal.tsx +++ b/protocol-designer/src/components/modules/TrashModal.tsx @@ -1,4 +1,5 @@ import * as React from 'react' +import { useTranslation } from 'react-i18next' import { useSelector, useDispatch } from 'react-redux' import { Form, Formik, useField, useFormikContext } from 'formik' import { @@ -24,7 +25,6 @@ import { getDeckDefFromRobotType, WASTE_CHUTE_CUTOUT, } from '@opentrons/shared-data' -import { i18n } from '../../localization' import { createDeckFixture, deleteDeckFixture, @@ -75,6 +75,7 @@ export const MOVABLE_TRASH_CUTOUTS: DropdownOption[] = [ const TrashModalComponent = (props: TrashModalProps): JSX.Element => { const { onCloseClick, trashName } = props + const { t } = useTranslation(['alert', 'button']) const { values } = useFormikContext() const initialDeckSetup = useSelector(getInitialDeckSetup) const isSlotEmpty = getSlotIsEmpty( @@ -115,9 +116,7 @@ const TrashModalComponent = (props: TrashModalProps): JSX.Element => { {!isSlotEmpty ? ( ) : null} @@ -140,10 +139,10 @@ const TrashModalComponent = (props: TrashModalProps): JSX.Element => { gridGap={SPACING.spacing8} > - {i18n.t('button.cancel')} + {t('button:cancel')} - {i18n.t('button.save')} + {t('button:save')} @@ -159,6 +158,7 @@ export interface TrashModalProps { export const TrashModal = (props: TrashModalProps): JSX.Element => { const { onCloseClick, trashName, trashBinId } = props const dispatch = useDispatch() + const { t } = useTranslation('modules') const onSaveClick = (values: TrashValues): void => { if (trashName === 'trashBin' && trashBinId == null) { @@ -184,7 +184,7 @@ export const TrashModal = (props: TrashModalProps): JSX.Element => { - {i18n.t(`modules.additional_equipment_display_names.${trashName}`)} + {t(`additional_equipment_display_names.${trashName}`)}