From 75de20af6a2ad290f9e2729d1e41feb96de4354b Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 12 Oct 2023 21:34:24 +1100 Subject: [PATCH 1/3] fix(ui): fix plurals in translation --- invokeai/frontend/web/public/locales/en.json | 17 +++++++------ .../listeners/batchEnqueued.ts | 2 +- .../listeners/modelSelected.ts | 11 +++----- .../SettingsClearIntermediates.tsx | 25 +++++-------------- 4 files changed, 19 insertions(+), 36 deletions(-) diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index 2e6df644a2..b6bad9b3cd 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -275,7 +275,8 @@ "batchValues": "Batch Values", "notReady": "Unable to Queue", "batchQueued": "Batch Queued", - "batchQueuedDesc": "Added {{item_count}} sessions to {{direction}} of queue", + "batchQueuedDesc_one": "Added {{count}} sessions to {{direction}} of queue", + "batchQueuedDesc_other": "Added {{count}} sessions to {{direction}} of queue", "front": "front", "back": "back", "batchFailedToQueue": "Failed to Queue Batch", @@ -1111,17 +1112,17 @@ "clearIntermediatesDesc2": "Intermediate images are byproducts of generation, different from the result images in the gallery. Clearing intermediates will free disk space.", "clearIntermediatesDesc3": "Your gallery images will not be deleted.", "clearIntermediates": "Clear Intermediates", - "clearIntermediates_one": "Clear 1 Intermediate", - "clearIntermediates_other": "Clear {{number}} Intermediates", - "noIntermediates": "No Intermediates to Clear", - "intermediatesCleared_one": "Cleared 1 Intermediate", - "intermediatesCleared_other": "Cleared {{number}} Intermediates", + "clearIntermediatesWithCount_one": "Clear {{count}} Intermediate", + "clearIntermediatesWithCount_other": "Clear {{count}} Intermediates", + "clearIntermediatesWithCount_zero": "No Intermediates to Clear", + "intermediatesCleared_one": "Cleared {{count}} Intermediate", + "intermediatesCleared_other": "Cleared {{count}} Intermediates", "intermediatesClearedFailed": "Problem Clearing Intermediates" }, "toast": { "addedToBoard": "Added to board", - "baseModelChangedCleared_one": "Base model changed, cleared or disabled {{number}} incompatible submodel", - "baseModelChangedCleared_many": "$t(toast.baseModelChangedCleared_one)s", + "baseModelChangedCleared_one": "Base model changed, cleared or disabled {{count}} incompatible submodel", + "baseModelChangedCleared_other": "Base model changed, cleared or disabled {{count}} incompatible submodels", "canceled": "Processing Canceled", "canvasCopiedClipboard": "Canvas Copied to Clipboard", "canvasDownloaded": "Canvas Downloaded", diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/batchEnqueued.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/batchEnqueued.ts index bdb8e03ad2..62a661756b 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/batchEnqueued.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/batchEnqueued.ts @@ -30,7 +30,7 @@ export const addBatchEnqueuedListener = () => { id: 'batch-queued', title: t('queue.batchQueued'), description: t('queue.batchQueuedDesc', { - item_count: response.enqueued, + count: response.enqueued, direction: arg.prepend ? t('queue.front') : t('queue.back'), }), duration: 1000, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts index c320c437f6..6ed0b93e99 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts @@ -73,14 +73,9 @@ export const addModelSelectedListener = () => { dispatch( addToast( makeToast({ - title: t( - modelsCleared === 1 - ? 'toast.baseModelChangedCleared_one' - : 'toast.baseModelChangedCleared_many', - { - number: modelsCleared, - } - ), + title: t('toast.baseModelChangedCleared', { + count: modelsCleared, + }), status: 'warning', }) ) diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsClearIntermediates.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsClearIntermediates.tsx index 4282b849c3..423ce41bcd 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsClearIntermediates.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsClearIntermediates.tsx @@ -1,7 +1,7 @@ import { Heading, Text } from '@chakra-ui/react'; import { useAppDispatch } from 'app/store/storeHooks'; import { controlAdaptersReset } from 'features/controlAdapters/store/controlAdaptersSlice'; -import { useCallback, useEffect, useMemo } from 'react'; +import { useCallback, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import IAIButton from '../../../../common/components/IAIButton'; import { @@ -25,15 +25,12 @@ export default function SettingsClearIntermediates() { const handleClickClearIntermediates = useCallback(() => { clearIntermediates() .unwrap() - .then((number) => { + .then((clearedCount) => { dispatch(controlAdaptersReset()); dispatch(resetCanvas()); dispatch( addToast({ - title: - number === 1 - ? t('settings.intermediatesCleared_one') - : t('settings.intermediatesCleared_other', { number }), + title: t('settings.intermediatesCleared', { count: clearedCount }), status: 'info', }) ); @@ -53,18 +50,6 @@ export default function SettingsClearIntermediates() { updateIntermediatesCount(); }, [updateIntermediatesCount]); - const buttonText = useMemo(() => { - if (!intermediatesCount) { - return t('settings.noIntermediates'); - } - if (intermediatesCount === 1) { - return t('settings.clearIntermediates_one'); - } - return t('settings.clearIntermediates_other', { - number: intermediatesCount, - }); - }, [intermediatesCount, t]); - return ( {t('settings.clearIntermediates')} @@ -74,7 +59,9 @@ export default function SettingsClearIntermediates() { isLoading={isLoadingClearIntermediates} isDisabled={!intermediatesCount} > - {buttonText} + {t('settings.clearIntermediatesWithCount', { + count: intermediatesCount ?? 0, + })} {t('settings.clearIntermediatesDesc1')} {t('settings.clearIntermediatesDesc2')} From 18164fc72a830766e8f0038a67a6f1ca045450cd Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 12 Oct 2023 21:36:38 +1100 Subject: [PATCH 2/3] fix(ui): prettier ignores translation files --- invokeai/frontend/web/.prettierignore | 1 + 1 file changed, 1 insertion(+) diff --git a/invokeai/frontend/web/.prettierignore b/invokeai/frontend/web/.prettierignore index 0c18899000..bdf02d5c9e 100644 --- a/invokeai/frontend/web/.prettierignore +++ b/invokeai/frontend/web/.prettierignore @@ -1,4 +1,5 @@ dist/ +public/locales/*.json .husky/ node_modules/ patches/ From 89db749d8940b35a30878410cd75d44c2ebfb714 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 12 Oct 2023 22:46:47 +1100 Subject: [PATCH 3/3] fix(ui): add missing translation strings --- invokeai/frontend/web/public/locales/en.json | 7 ++++++- .../features/canvas/components/IAICanvasStatusText.tsx | 10 ++++++---- .../components/ControlAdaptersCollapse.tsx | 7 ++++++- .../features/gallery/components/Boards/AutoAddIcon.tsx | 4 +++- .../gallery/components/ImageGalleryContent.tsx | 6 ++++-- .../src/features/lora/components/ParamLoraCollapse.tsx | 4 +++- .../components/Parameters/Core/ParamAspectRatio.tsx | 3 ++- .../Parameters/VAEModel/ParamVAEPrecision.tsx | 4 +++- .../features/queue/components/QueueButtonTooltip.tsx | 4 ++-- .../components/SDXLImageToImageTabCoreParameters.tsx | 8 +++++++- .../components/SDXLUnifiedCanvasTabCoreParameters.tsx | 8 +++++++- .../ImageToImage/ImageToImageTabCoreParameters.tsx | 4 +++- .../tabs/TextToImage/TextToImageTabCoreParameters.tsx | 4 +++- .../tabs/UnifiedCanvas/UnifiedCanvasCoreParameters.tsx | 4 +++- .../web/src/services/api/hooks/useBoardName.ts | 3 ++- 15 files changed, 60 insertions(+), 20 deletions(-) diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index b6bad9b3cd..e0baefcf9e 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -45,10 +45,12 @@ "accept": "Accept", "advanced": "Advanced", "areYouSure": "Are you sure?", + "auto": "Auto", "back": "Back", "batch": "Batch Manager", "cancel": "Cancel", "close": "Close", + "on": "On", "communityLabel": "Community", "controlNet": "ControlNet", "controlAdapter": "Control Adapter", @@ -133,7 +135,8 @@ "upload": "Upload" }, "controlnet": { - "controlAdapter": "Control Adapter", + "controlAdapter_one": "Control Adapter", + "controlAdapter_other": "Control Adapters", "controlnet": "$t(controlnet.controlAdapter) #{{number}} ($t(common.controlNet))", "ip_adapter": "$t(controlnet.controlAdapter) #{{number}} ($t(common.ipAdapter))", "t2i_adapter": "$t(controlnet.controlAdapter) #{{number}} ($t(common.t2iAdapter))", @@ -702,6 +705,7 @@ "vae": "VAE", "vaeLocation": "VAE Location", "vaeLocationValidationMsg": "Path to where your VAE is located.", + "vaePrecision": "VAE Precision", "vaeRepoID": "VAE Repo ID", "vaeRepoIDValidationMsg": "Online repository of your VAE", "variant": "Variant", @@ -922,6 +926,7 @@ }, "parameters": { "aspectRatio": "Aspect Ratio", + "aspectRatioFree": "Free", "boundingBoxHeader": "Bounding Box", "boundingBoxHeight": "Bounding Box Height", "boundingBoxWidth": "Bounding Box Width", diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx index 7aa9cad003..2b13e5cf6b 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx @@ -45,7 +45,7 @@ const selector = createSelector( return { activeLayerColor, - activeLayerString: layer.charAt(0).toUpperCase() + layer.slice(1), + layer, boundingBoxColor, boundingBoxCoordinatesString: `(${roundToHundreth( boxX @@ -73,7 +73,7 @@ const selector = createSelector( const IAICanvasStatusText = () => { const { activeLayerColor, - activeLayerString, + layer, boundingBoxColor, boundingBoxCoordinatesString, boundingBoxDimensionsString, @@ -116,7 +116,9 @@ const IAICanvasStatusText = () => { style={{ color: activeLayerColor, }} - >{`${t('unifiedCanvas.activeLayer')}: ${activeLayerString}`} + >{`${t('unifiedCanvas.activeLayer')}: ${t( + `unifiedCanvas.${layer}` + )}`} {`${t('unifiedCanvas.canvasScale')}: ${canvasScaleString}%`} {shouldPreserveMaskedArea && ( { color: warningColor, }} > - Preserve Masked Area: On + {t('unifiedCanvas.preserveMaskedArea')}: {t('common.on')} )} {shouldShowBoundingBox && ( diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdaptersCollapse.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdaptersCollapse.tsx index b2f9bcfe41..d1c3f6f0b9 100644 --- a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdaptersCollapse.tsx +++ b/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdaptersCollapse.tsx @@ -89,7 +89,12 @@ const ControlAdaptersCollapse = () => { } return ( - + { + const { t } = useTranslation(); return ( { variant="solid" sx={{ bg: 'accent.400', _dark: { bg: 'accent.500' } }} > - auto + {t('common.auto')} ); diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx index 63e0cee378..fa640bf202 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx @@ -20,6 +20,7 @@ import BoardsList from './Boards/BoardsList/BoardsList'; import GalleryBoardName from './GalleryBoardName'; import GallerySettingsPopover from './GallerySettingsPopover'; import GalleryImageGrid from './ImageGrid/GalleryImageGrid'; +import { useTranslation } from 'react-i18next'; const selector = createSelector( [stateSelector], @@ -34,6 +35,7 @@ const selector = createSelector( ); const ImageGalleryContent = () => { + const { t } = useTranslation(); const resizeObserverRef = useRef(null); const galleryGridRef = useRef(null); const { galleryView } = useAppSelector(selector); @@ -111,7 +113,7 @@ const ImageGalleryContent = () => { leftIcon={} data-testid="images-tab" > - Images + {t('gallery.images')} { leftIcon={} data-testid="assets-tab" > - Assets + {t('gallery.assets')} diff --git a/invokeai/frontend/web/src/features/lora/components/ParamLoraCollapse.tsx b/invokeai/frontend/web/src/features/lora/components/ParamLoraCollapse.tsx index c2edd94106..4f6fe26f1d 100644 --- a/invokeai/frontend/web/src/features/lora/components/ParamLoraCollapse.tsx +++ b/invokeai/frontend/web/src/features/lora/components/ParamLoraCollapse.tsx @@ -9,6 +9,7 @@ import { memo } from 'react'; import { useFeatureStatus } from '../../system/hooks/useFeatureStatus'; import ParamLoraList from './ParamLoraList'; import ParamLoRASelect from './ParamLoraSelect'; +import { useTranslation } from 'react-i18next'; const selector = createSelector( stateSelector, @@ -22,6 +23,7 @@ const selector = createSelector( ); const ParamLoraCollapse = () => { + const { t } = useTranslation(); const { activeLabel } = useAppSelector(selector); const isLoraEnabled = useFeatureStatus('lora').isFeatureEnabled; @@ -31,7 +33,7 @@ const ParamLoraCollapse = () => { } return ( - + diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx index 3a5cc264e7..19d707765b 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx @@ -6,10 +6,11 @@ import { setAspectRatio, setShouldLockAspectRatio, } from 'features/parameters/store/generationSlice'; +import i18next from 'i18next'; import { activeTabNameSelector } from '../../../../ui/store/uiSelectors'; const aspectRatios = [ - { name: 'Free', value: null }, + { name: i18next.t('parameters.aspectRatioFree'), value: null }, { name: '2:3', value: 2 / 3 }, { name: '16:9', value: 16 / 9 }, { name: '1:1', value: 1 / 1 }, diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/VAEModel/ParamVAEPrecision.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/VAEModel/ParamVAEPrecision.tsx index f71794394e..723e57a288 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/VAEModel/ParamVAEPrecision.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/VAEModel/ParamVAEPrecision.tsx @@ -7,6 +7,7 @@ import IAIMantineSelect from 'common/components/IAIMantineSelect'; import { vaePrecisionChanged } from 'features/parameters/store/generationSlice'; import { PrecisionParam } from 'features/parameters/types/parameterSchemas'; import { memo, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; const selector = createSelector( stateSelector, @@ -20,6 +21,7 @@ const selector = createSelector( const DATA = ['fp16', 'fp32']; const ParamVAEModelSelect = () => { + const { t } = useTranslation(); const dispatch = useAppDispatch(); const { vaePrecision } = useAppSelector(selector); @@ -37,7 +39,7 @@ const ParamVAEModelSelect = () => { return ( { )} - Adding images to{' '} + {t('parameters.invoke.addingImagesTo')}{' '} - {autoAddBoardName || 'Uncategorized'} + {autoAddBoardName || t('boards.uncategorized')} diff --git a/invokeai/frontend/web/src/features/sdxl/components/SDXLImageToImageTabCoreParameters.tsx b/invokeai/frontend/web/src/features/sdxl/components/SDXLImageToImageTabCoreParameters.tsx index dae462ad47..d107503dc6 100644 --- a/invokeai/frontend/web/src/features/sdxl/components/SDXLImageToImageTabCoreParameters.tsx +++ b/invokeai/frontend/web/src/features/sdxl/components/SDXLImageToImageTabCoreParameters.tsx @@ -14,6 +14,7 @@ import { generationSelector } from 'features/parameters/store/generationSelector import { uiSelector } from 'features/ui/store/uiSelectors'; import { memo } from 'react'; import ParamSDXLImg2ImgDenoisingStrength from './ParamSDXLImg2ImgDenoisingStrength'; +import { useTranslation } from 'react-i18next'; const selector = createSelector( [uiSelector, generationSelector], @@ -29,10 +30,15 @@ const selector = createSelector( ); const SDXLImageToImageTabCoreParameters = () => { + const { t } = useTranslation(); const { shouldUseSliders, activeLabel } = useAppSelector(selector); return ( - + { + const { t } = useTranslation(); const { shouldUseSliders, activeLabel } = useAppSelector(selector); return ( - + { + const { t } = useTranslation(); const shouldUseSliders = useAppSelector((state) => state.ui.shouldUseSliders); const { iterationsAndSeedLabel } = useCoreParametersCollapseLabel(); return ( diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters.tsx index ea6ef03e09..3f3cf2db05 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters.tsx @@ -9,14 +9,16 @@ import ParamSteps from 'features/parameters/components/Parameters/Core/ParamStep import ParamSeedFull from 'features/parameters/components/Parameters/Seed/ParamSeedFull'; import { useCoreParametersCollapseLabel } from 'features/parameters/util/useCoreParametersCollapseLabel'; import { memo } from 'react'; +import { useTranslation } from 'react-i18next'; const TextToImageTabCoreParameters = () => { + const { t } = useTranslation(); const shouldUseSliders = useAppSelector((state) => state.ui.shouldUseSliders); const { iterationsAndSeedLabel } = useCoreParametersCollapseLabel(); return ( diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasCoreParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasCoreParameters.tsx index c57a68ed62..40a5026d09 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasCoreParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasCoreParameters.tsx @@ -10,14 +10,16 @@ import ImageToImageStrength from 'features/parameters/components/Parameters/Imag import ParamSeedFull from 'features/parameters/components/Parameters/Seed/ParamSeedFull'; import { useCoreParametersCollapseLabel } from 'features/parameters/util/useCoreParametersCollapseLabel'; import { memo } from 'react'; +import { useTranslation } from 'react-i18next'; const UnifiedCanvasCoreParameters = () => { + const { t } = useTranslation(); const shouldUseSliders = useAppSelector((state) => state.ui.shouldUseSliders); const { iterationsAndSeedLabel } = useCoreParametersCollapseLabel(); return ( diff --git a/invokeai/frontend/web/src/services/api/hooks/useBoardName.ts b/invokeai/frontend/web/src/services/api/hooks/useBoardName.ts index ce0cff7b8a..54e3745c27 100644 --- a/invokeai/frontend/web/src/services/api/hooks/useBoardName.ts +++ b/invokeai/frontend/web/src/services/api/hooks/useBoardName.ts @@ -1,11 +1,12 @@ import { BoardId } from 'features/gallery/store/types'; import { useListAllBoardsQuery } from '../endpoints/boards'; +import { t } from 'i18next'; export const useBoardName = (board_id: BoardId) => { const { boardName } = useListAllBoardsQuery(undefined, { selectFromResult: ({ data }) => { const selectedBoard = data?.find((b) => b.board_id === board_id); - const boardName = selectedBoard?.board_name || 'Uncategorized'; + const boardName = selectedBoard?.board_name || t('boards.uncategorized'); return { boardName }; },