mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
eslint added to enforce translations (#5150)
* eslint added and new string added * strings and translation hook added * more changes made * missing translation added * final errors resolve in progress * all errors resolved * fix(ui): fix missing import of `t()` * fix(ui): use plurals for moving images to board translation * fix(ui): fix typo in translation key * fix(ui): do not use translation for "invoke ai" * chore(ui): lint --------- Co-authored-by: psychedelicious <4822129+psychedelicious@users.noreply.github.com>
This commit is contained in:
parent
667a2a3d84
commit
6e6d903f99
@ -20,10 +20,16 @@ module.exports = {
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['react', '@typescript-eslint', 'eslint-plugin-react-hooks'],
|
||||
plugins: [
|
||||
'react',
|
||||
'@typescript-eslint',
|
||||
'eslint-plugin-react-hooks',
|
||||
'i18next',
|
||||
],
|
||||
root: true,
|
||||
rules: {
|
||||
curly: 'error',
|
||||
'i18next/no-literal-string': 2,
|
||||
'react/jsx-no-bind': ['error', { allowBind: true }],
|
||||
'react/jsx-curly-brace-presence': [
|
||||
'error',
|
||||
|
@ -131,6 +131,7 @@
|
||||
"concurrently": "^8.2.2",
|
||||
"eslint": "^8.53.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-i18next": "^6.0.3",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"husky": "^8.0.3",
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"accessibility": {
|
||||
"copyMetadataJson": "Copy metadata JSON",
|
||||
"createIssue":"Create Issue",
|
||||
"exitViewer": "Exit Viewer",
|
||||
"flipHorizontally": "Flip Horizontally",
|
||||
"flipVertically": "Flip Vertically",
|
||||
@ -12,6 +13,7 @@
|
||||
"nextImage": "Next Image",
|
||||
"previousImage": "Previous Image",
|
||||
"reset": "Reset",
|
||||
"resetUI":"$t(accessibility.reset) UI",
|
||||
"rotateClockwise": "Rotate Clockwise",
|
||||
"rotateCounterClockwise": "Rotate Counter-Clockwise",
|
||||
"showGalleryPanel": "Show Gallery Panel",
|
||||
@ -38,6 +40,8 @@
|
||||
"loading": "Loading...",
|
||||
"menuItemAutoAdd": "Auto-add to this Board",
|
||||
"move": "Move",
|
||||
"movingImagesToBoard_one": "Moving {{count}} image to board:",
|
||||
"movingImagesToBoard_other": "Moving {{count}} images to board:",
|
||||
"myBoard": "My Board",
|
||||
"noMatching": "No matching Boards",
|
||||
"searchBoard": "Search Boards...",
|
||||
@ -49,11 +53,13 @@
|
||||
"common": {
|
||||
"accept": "Accept",
|
||||
"advanced": "Advanced",
|
||||
"ai": "ai",
|
||||
"areYouSure": "Are you sure?",
|
||||
"auto": "Auto",
|
||||
"back": "Back",
|
||||
"batch": "Batch Manager",
|
||||
"cancel": "Cancel",
|
||||
"copyError":"$t(gallery.copy) Error",
|
||||
"close": "Close",
|
||||
"on": "On",
|
||||
"checkpoint": "Checkpoint",
|
||||
@ -67,6 +73,10 @@
|
||||
"darkMode": "Dark Mode",
|
||||
"discordLabel": "Discord",
|
||||
"dontAskMeAgain": "Don't ask me again",
|
||||
"error": "Error",
|
||||
"file": "File",
|
||||
"folder": "Folder",
|
||||
"format":"format",
|
||||
"generate": "Generate",
|
||||
"githubLabel": "Github",
|
||||
"hotkeysLabel": "Hotkeys",
|
||||
@ -74,6 +84,8 @@
|
||||
"imageFailedToLoad": "Unable to Load Image",
|
||||
"img2img": "Image To Image",
|
||||
"inpaint": "inpaint",
|
||||
"input": "Input",
|
||||
"installed": "Installed",
|
||||
"langArabic": "العربية",
|
||||
"langBrPortuguese": "Português do Brasil",
|
||||
"langDutch": "Nederlands",
|
||||
@ -101,6 +113,7 @@
|
||||
"nodeEditor": "Node Editor",
|
||||
"nodes": "Workflow Editor",
|
||||
"nodesDesc": "A node based system for the generation of images is under development currently. Stay tuned for updates about this amazing feature.",
|
||||
"notInstalled": "Not $t(common.installed)",
|
||||
"openInNewTab": "Open in New Tab",
|
||||
"outpaint": "outpaint",
|
||||
"outputs": "Outputs",
|
||||
@ -114,6 +127,7 @@
|
||||
"safetensors": "Safetensors",
|
||||
"settingsLabel": "Settings",
|
||||
"simple": "Simple",
|
||||
"somethingWentWrong": "Something went wrong",
|
||||
"statusConnected": "Connected",
|
||||
"statusConvertingModel": "Converting Model",
|
||||
"statusDisconnected": "Disconnected",
|
||||
@ -252,6 +266,7 @@
|
||||
"embedding": {
|
||||
"addEmbedding": "Add Embedding",
|
||||
"incompatibleModel": "Incompatible base model:",
|
||||
"noEmbeddingsLoaded": "No Embeddings Loaded",
|
||||
"noMatchingEmbedding": "No matching Embeddings"
|
||||
},
|
||||
"queue": {
|
||||
@ -330,7 +345,8 @@
|
||||
"enableFailed": "Problem Enabling Invocation Cache",
|
||||
"disable": "Disable",
|
||||
"disableSucceeded": "Invocation Cache Disabled",
|
||||
"disableFailed": "Problem Disabling Invocation Cache"
|
||||
"disableFailed": "Problem Disabling Invocation Cache",
|
||||
"useCache": "Use Cache"
|
||||
},
|
||||
"gallery": {
|
||||
"allImagesLoaded": "All Images Loaded",
|
||||
@ -339,6 +355,9 @@
|
||||
"autoSwitchNewImages": "Auto-Switch to New Images",
|
||||
"copy": "Copy",
|
||||
"currentlyInUse": "This image is currently in use in the following features:",
|
||||
"drop":"Drop",
|
||||
"dropOrUpload":"$t(gallery.drop) or Upload",
|
||||
"dropToUpload":"$t(gallery.drop) to Upload",
|
||||
"deleteImage": "Delete Image",
|
||||
"deleteImageBin": "Deleted images will be sent to your operating system's Bin.",
|
||||
"deleteImagePermanent": "Deleted images cannot be restored.",
|
||||
@ -348,7 +367,7 @@
|
||||
"galleryImageSize": "Image Size",
|
||||
"gallerySettings": "Gallery Settings",
|
||||
"generations": "Generations",
|
||||
"images": "Images",
|
||||
"image": "image",
|
||||
"loading": "Loading",
|
||||
"loadMore": "Load More",
|
||||
"maintainAspectRatio": "Maintain Aspect Ratio",
|
||||
@ -360,6 +379,7 @@
|
||||
"singleColumnLayout": "Single Column Layout",
|
||||
"unableToLoad": "Unable to load Gallery",
|
||||
"uploads": "Uploads",
|
||||
"deleteSelection": "Delete Selection",
|
||||
"downloadSelection": "Download Selection",
|
||||
"preparingDownload": "Preparing Download",
|
||||
"preparingDownloadFailed": "Problem Preparing Download"
|
||||
@ -629,6 +649,7 @@
|
||||
"closeAdvanced": "Close Advanced",
|
||||
"config": "Config",
|
||||
"configValidationMsg": "Path to the config file of your model.",
|
||||
"conversionNotSupported": "Conversion Not Supported",
|
||||
"convert": "Convert",
|
||||
"convertingModelBegin": "Converting Model. Please wait.",
|
||||
"convertToDiffusers": "Convert To Diffusers",
|
||||
@ -754,6 +775,7 @@
|
||||
"esrganModel": "ESRGAN Model",
|
||||
"loading": "loading",
|
||||
"noLoRAsAvailable": "No LoRAs available",
|
||||
"noLoRAsLoaded":"No LoRAs Loaded",
|
||||
"noMatchingLoRAs": "No matching LoRAs",
|
||||
"noMatchingModels": "No matching Models",
|
||||
"noModelsAvailable": "No models available",
|
||||
@ -765,6 +787,7 @@
|
||||
"nodes": {
|
||||
"addNode": "Add Node",
|
||||
"addNodeToolTip": "Add Node (Shift+A, Space)",
|
||||
"addLinearView":"Add to Linear View",
|
||||
"animatedEdges": "Animated Edges",
|
||||
"animatedEdgesHelp": "Animate selected edges and edges connected to selected nodes",
|
||||
"boardField": "Board",
|
||||
@ -885,6 +908,7 @@
|
||||
"noMatchingNodes": "No matching nodes",
|
||||
"noNodeSelected": "No node selected",
|
||||
"nodeOpacity": "Node Opacity",
|
||||
"nodeVersion": "Node Version",
|
||||
"noOutputRecorded": "No outputs recorded",
|
||||
"noOutputSchemaName": "No output schema name found in ref object",
|
||||
"notes": "Notes",
|
||||
@ -892,6 +916,7 @@
|
||||
"oNNXModelField": "ONNX Model",
|
||||
"oNNXModelFieldDescription": "ONNX model field.",
|
||||
"outputField": "Output Field",
|
||||
"outputFieldInInput": "Output field in input",
|
||||
"outputFields": "Output Fields",
|
||||
"outputNode": "Output node",
|
||||
"outputSchemaNotFound": "Output schema not found",
|
||||
@ -937,10 +962,14 @@
|
||||
"uNetFieldDescription": "UNet submodel.",
|
||||
"unhandledInputProperty": "Unhandled input property",
|
||||
"unhandledOutputProperty": "Unhandled output property",
|
||||
"unknownField": "Unknown Field",
|
||||
"unknownField": "Unknown field",
|
||||
"unknownFieldType": "$(nodes.unknownField) type",
|
||||
"unknownNode": "Unknown Node",
|
||||
"unknownNodeType":"$t(nodes.unknownNode) type",
|
||||
"unknownTemplate": "Unknown Template",
|
||||
"unknownInput": "Unknown input",
|
||||
"unkownInvocation": "Unknown Invocation type",
|
||||
"unknownOutput": "Unknown output",
|
||||
"updateNode": "Update Node",
|
||||
"updateAllNodes": "Update All Nodes",
|
||||
"updateApp": "Update App",
|
||||
@ -1171,7 +1200,8 @@
|
||||
"clearIntermediatesWithCount_other": "Clear {{count}} Intermediates",
|
||||
"intermediatesCleared_one": "Cleared {{count}} Intermediate",
|
||||
"intermediatesCleared_other": "Cleared {{count}} Intermediates",
|
||||
"intermediatesClearedFailed": "Problem Clearing Intermediates"
|
||||
"intermediatesClearedFailed": "Problem Clearing Intermediates",
|
||||
"reloadingIn": "Reloading in"
|
||||
},
|
||||
"toast": {
|
||||
"addedToBoard": "Added to board",
|
||||
@ -1199,6 +1229,7 @@
|
||||
"initialImageNotSet": "Initial Image Not Set",
|
||||
"initialImageNotSetDesc": "Could not load initial image",
|
||||
"initialImageSet": "Initial Image Set",
|
||||
"invalidUpload": "Invalid Upload",
|
||||
"loadedWithWarnings": "Workflow Loaded with Warnings",
|
||||
"maskSavedAssets": "Mask Saved to Assets",
|
||||
"maskSentControlnetAssets": "Mask Sent to ControlNet & Assets",
|
||||
@ -1517,7 +1548,7 @@
|
||||
"clearCanvasHistoryConfirm": "Are you sure you want to clear the canvas history?",
|
||||
"clearCanvasHistoryMessage": "Clearing the canvas history leaves your current canvas intact, but irreversibly clears the undo and redo history.",
|
||||
"clearHistory": "Clear History",
|
||||
"clearMask": "Clear Mask",
|
||||
"clearMask": "Clear Mask (Shift+C)",
|
||||
"colorPicker": "Color Picker",
|
||||
"copyToClipboard": "Copy to Clipboard",
|
||||
"cursorPosition": "Cursor Position",
|
||||
@ -1544,6 +1575,7 @@
|
||||
"redo": "Redo",
|
||||
"resetView": "Reset View",
|
||||
"saveBoxRegionOnly": "Save Box Region Only",
|
||||
"saveMask":"Save $t(unifiedCanvas.mask)",
|
||||
"saveToGallery": "Save To Gallery",
|
||||
"scaledBoundingBox": "Scaled Bounding Box",
|
||||
"showCanvasDebugInfo": "Show Additional Canvas Info",
|
||||
|
@ -2,6 +2,7 @@ import { Flex, Heading, Link, Text, useToast } from '@chakra-ui/react';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import newGithubIssueUrl from 'new-github-issue-url';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaCopy, FaExternalLinkAlt } from 'react-icons/fa';
|
||||
import { FaArrowRotateLeft } from 'react-icons/fa6';
|
||||
import { serializeError } from 'serialize-error';
|
||||
@ -13,6 +14,7 @@ type Props = {
|
||||
|
||||
const AppErrorBoundaryFallback = ({ error, resetErrorBoundary }: Props) => {
|
||||
const toast = useToast();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleCopy = useCallback(() => {
|
||||
const text = JSON.stringify(serializeError(error), null, 2);
|
||||
@ -53,7 +55,7 @@ const AppErrorBoundaryFallback = ({ error, resetErrorBoundary }: Props) => {
|
||||
p: 16,
|
||||
}}
|
||||
>
|
||||
<Heading>Something went wrong</Heading>
|
||||
<Heading>{t('common.somethingWentWrong')}</Heading>
|
||||
<Flex
|
||||
layerStyle="second"
|
||||
sx={{
|
||||
@ -80,13 +82,15 @@ const AppErrorBoundaryFallback = ({ error, resetErrorBoundary }: Props) => {
|
||||
leftIcon={<FaArrowRotateLeft />}
|
||||
onClick={resetErrorBoundary}
|
||||
>
|
||||
Reset UI
|
||||
{t('accessibility.resetUI')}
|
||||
</IAIButton>
|
||||
<IAIButton leftIcon={<FaCopy />} onClick={handleCopy}>
|
||||
Copy Error
|
||||
{t('common.copyError')}
|
||||
</IAIButton>
|
||||
<Link href={url} isExternal>
|
||||
<IAIButton leftIcon={<FaExternalLinkAlt />}>Create Issue</IAIButton>
|
||||
<IAIButton leftIcon={<FaExternalLinkAlt />}>
|
||||
{t('accessibility.createIssue')}
|
||||
</IAIButton>
|
||||
</Link>
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Box, Flex, Heading } from '@chakra-ui/react';
|
||||
import { memo } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
type ImageUploadOverlayProps = {
|
||||
isDragAccept: boolean;
|
||||
@ -9,6 +10,7 @@ type ImageUploadOverlayProps = {
|
||||
};
|
||||
|
||||
const ImageUploadOverlay = (props: ImageUploadOverlayProps) => {
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
isDragAccept,
|
||||
isDragReject: _isDragAccept,
|
||||
@ -76,11 +78,13 @@ const ImageUploadOverlay = (props: ImageUploadOverlayProps) => {
|
||||
}}
|
||||
>
|
||||
{isDragAccept ? (
|
||||
<Heading size="lg">Drop to Upload</Heading>
|
||||
<Heading size="lg">{t('gallery.dropToUpload')}</Heading>
|
||||
) : (
|
||||
<>
|
||||
<Heading size="lg">Invalid Upload</Heading>
|
||||
<Heading size="md">Must be single JPEG or PNG image</Heading>
|
||||
<Heading size="lg">{t('toast.invalidUpload')}</Heading>
|
||||
<Heading size="md">
|
||||
{t('toast.uploadFailedInvalidUploadDesc')}
|
||||
</Heading>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
|
@ -155,10 +155,10 @@ const IAICanvasMaskOptions = () => {
|
||||
<IAIColorPicker color={maskColor} onChange={handleChangeMaskColor} />
|
||||
</Box>
|
||||
<IAIButton size="sm" leftIcon={<FaSave />} onClick={handleSaveMask}>
|
||||
Save Mask
|
||||
{t('unifiedCanvas.saveMask')}
|
||||
</IAIButton>
|
||||
<IAIButton size="sm" leftIcon={<FaTrash />} onClick={handleClearMask}>
|
||||
{t('unifiedCanvas.clearMask')} (Shift+C)
|
||||
{t('unifiedCanvas.clearMask')}
|
||||
</IAIButton>
|
||||
</Flex>
|
||||
</IAIPopover>
|
||||
|
@ -110,8 +110,10 @@ const ChangeBoardModal = () => {
|
||||
<AlertDialogBody>
|
||||
<Flex sx={{ flexDir: 'column', gap: 4 }}>
|
||||
<Text>
|
||||
Moving {`${imagesToChange.length}`} image
|
||||
{`${imagesToChange.length > 1 ? 's' : ''}`} to board:
|
||||
{t('boards.movingImagesToBoard', {
|
||||
count: imagesToChange.length,
|
||||
})}
|
||||
:
|
||||
</Text>
|
||||
<IAIMantineSearchableSelect
|
||||
placeholder={
|
||||
|
@ -124,10 +124,10 @@ const DeleteImageModal = () => {
|
||||
</AlertDialogBody>
|
||||
<AlertDialogFooter>
|
||||
<IAIButton ref={cancelRef} onClick={handleClose}>
|
||||
Cancel
|
||||
{t('boards.cancel')}
|
||||
</IAIButton>
|
||||
<IAIButton colorScheme="error" onClick={handleDelete} ml={3}>
|
||||
Delete
|
||||
{t('controlnet.delete')}
|
||||
</IAIButton>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Box, ChakraProps, Flex, Heading, Image, Text } from '@chakra-ui/react';
|
||||
import { memo } from 'react';
|
||||
import { TypesafeDraggableData } from '../types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
type OverlayDragImageProps = {
|
||||
dragData: TypesafeDraggableData | null;
|
||||
@ -26,6 +27,7 @@ const STYLES: ChakraProps['sx'] = {
|
||||
};
|
||||
|
||||
const DragPreview = (props: OverlayDragImageProps) => {
|
||||
const { t } = useTranslation();
|
||||
if (!props.dragData) {
|
||||
return null;
|
||||
}
|
||||
@ -89,7 +91,7 @@ const DragPreview = (props: OverlayDragImageProps) => {
|
||||
}}
|
||||
>
|
||||
<Heading>{props.dragData.payload.imageDTOs.length}</Heading>
|
||||
<Heading size="sm">Images</Heading>
|
||||
<Heading size="sm">{t('parameters.images')}</Heading>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ const ParamEmbeddingPopover = (props: Props) => {
|
||||
_dark: { color: 'base.700' },
|
||||
}}
|
||||
>
|
||||
<Text>No Embeddings Loaded</Text>
|
||||
<Text>{t('embedding.noEmbeddingsLoaded')}</Text>
|
||||
</Flex>
|
||||
) : (
|
||||
<IAIMantineSearchableSelect
|
||||
|
@ -32,6 +32,7 @@ import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||
import { BoardDTO } from 'services/api/types';
|
||||
import AutoAddIcon from '../AutoAddIcon';
|
||||
import BoardContextMenu from '../BoardContextMenu';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface GalleryBoardProps {
|
||||
board: BoardDTO;
|
||||
@ -143,7 +144,7 @@ const GalleryBoard = ({
|
||||
const handleChange = useCallback((newBoardName: string) => {
|
||||
setLocalBoardName(newBoardName);
|
||||
}, []);
|
||||
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Box sx={{ w: 'full', h: 'full', touchAction: 'none', userSelect: 'none' }}>
|
||||
<Flex
|
||||
@ -292,7 +293,9 @@ const GalleryBoard = ({
|
||||
|
||||
<IAIDroppable
|
||||
data={droppableData}
|
||||
dropLabel={<Text fontSize="md">Move</Text>}
|
||||
dropLabel={
|
||||
<Text fontSize="md">{t('unifiedCanvas.move')}</Text>
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</Tooltip>
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
useGetBoardAssetsTotalQuery,
|
||||
useGetBoardImagesTotalQuery,
|
||||
} from 'services/api/endpoints/boards';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface Props {
|
||||
isSelected: boolean;
|
||||
@ -71,7 +72,7 @@ const NoBoardBoard = memo(({ isSelected }: Props) => {
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Box sx={{ w: 'full', h: 'full', touchAction: 'none', userSelect: 'none' }}>
|
||||
<Flex
|
||||
@ -161,7 +162,9 @@ const NoBoardBoard = memo(({ isSelected }: Props) => {
|
||||
/>
|
||||
<IAIDroppable
|
||||
data={droppableData}
|
||||
dropLabel={<Text fontSize="md">Move</Text>}
|
||||
dropLabel={
|
||||
<Text fontSize="md">{t('unifiedCanvas.move')}</Text>
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</Tooltip>
|
||||
|
@ -111,7 +111,7 @@ const MultipleSelectionMenuItems = () => {
|
||||
icon={<FaTrash />}
|
||||
onClickCapture={handleDeleteSelection}
|
||||
>
|
||||
Delete Selection
|
||||
{t('gallery.deleteSelection')}
|
||||
</MenuItem>
|
||||
</>
|
||||
);
|
||||
|
@ -113,7 +113,7 @@ const ImageGalleryContent = () => {
|
||||
leftIcon={<FaImages />}
|
||||
data-testid="images-tab"
|
||||
>
|
||||
{t('gallery.images')}
|
||||
{t('parameters.images')}
|
||||
</Tab>
|
||||
<Tab
|
||||
as={IAIButton}
|
||||
|
@ -49,7 +49,7 @@ const ImageMetadataViewer = ({ image }: ImageMetadataViewerProps) => {
|
||||
}}
|
||||
>
|
||||
<Flex gap={2}>
|
||||
<Text fontWeight="semibold">File:</Text>
|
||||
<Text fontWeight="semibold">{t('common.file')}:</Text>
|
||||
<Link href={image.image_url} isExternal maxW="calc(100% - 3rem)">
|
||||
{image.image_name}
|
||||
<ExternalLinkIcon mx="2px" />
|
||||
|
@ -165,7 +165,7 @@ export default function FoundModelsList() {
|
||||
},
|
||||
}}
|
||||
>
|
||||
Installed
|
||||
{t('common.installed')}
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
@ -215,7 +215,7 @@ export default function FoundModelsList() {
|
||||
/>
|
||||
<Flex p={2} gap={2}>
|
||||
<Text sx={{ fontWeight: 600 }}>
|
||||
Models Found: {foundModels.length}
|
||||
{t('modelManager.modelsFound')}: {foundModels.length}
|
||||
</Text>
|
||||
<Text
|
||||
sx={{
|
||||
@ -226,7 +226,7 @@ export default function FoundModelsList() {
|
||||
},
|
||||
}}
|
||||
>
|
||||
Not Installed: {filteredModels.length}
|
||||
{t('common.notInstalled')}: {filteredModels.length}
|
||||
</Text>
|
||||
</Flex>
|
||||
|
||||
|
@ -76,7 +76,7 @@ function SearchFolderForm() {
|
||||
_dark: { color: 'base.300' },
|
||||
}}
|
||||
>
|
||||
Folder
|
||||
{t('common.folder')}
|
||||
</Text>
|
||||
{!searchFolder ? (
|
||||
<IAIInput
|
||||
|
@ -114,7 +114,7 @@ export default function CheckpointModelEdit(props: CheckpointModelEditProps) {
|
||||
{model.model_name}
|
||||
</Text>
|
||||
<Text fontSize="sm" color="base.400">
|
||||
{MODEL_TYPE_MAP[model.base_model]} Model
|
||||
{MODEL_TYPE_MAP[model.base_model]} {t('modelManager.model')}
|
||||
</Text>
|
||||
</Flex>
|
||||
{![''].includes(model.base_model) ? (
|
||||
@ -128,7 +128,7 @@ export default function CheckpointModelEdit(props: CheckpointModelEditProps) {
|
||||
_dark: { bg: 'error.400' },
|
||||
}}
|
||||
>
|
||||
Conversion Not Supported
|
||||
{t('modelManager.conversionNotSupported')}
|
||||
</Badge>
|
||||
)}
|
||||
</Flex>
|
||||
|
@ -95,7 +95,7 @@ export default function DiffusersModelEdit(props: DiffusersModelEditProps) {
|
||||
{model.model_name}
|
||||
</Text>
|
||||
<Text fontSize="sm" color="base.400">
|
||||
{MODEL_TYPE_MAP[model.base_model]} Model
|
||||
{MODEL_TYPE_MAP[model.base_model]} {t('modelManager.model')}
|
||||
</Text>
|
||||
</Flex>
|
||||
<Divider />
|
||||
|
@ -95,8 +95,8 @@ export default function LoRAModelEdit(props: LoRAModelEditProps) {
|
||||
{model.model_name}
|
||||
</Text>
|
||||
<Text fontSize="sm" color="base.400">
|
||||
{MODEL_TYPE_MAP[model.base_model]} Model ⋅{' '}
|
||||
{LORA_MODEL_FORMAT_MAP[model.model_format]} format
|
||||
{MODEL_TYPE_MAP[model.base_model]} {t('modelManager.model')} ⋅{' '}
|
||||
{LORA_MODEL_FORMAT_MAP[model.model_format]} {t('common.format')}
|
||||
</Text>
|
||||
</Flex>
|
||||
<Divider />
|
||||
|
@ -10,6 +10,7 @@ import IAIDndImage from 'common/components/IAIDndImage';
|
||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||
import { DRAG_HANDLE_CLASSNAME } from 'features/nodes/types/constants';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createSelector(stateSelector, ({ system, gallery }) => {
|
||||
const imageDTO = gallery.selection[gallery.selection.length - 1];
|
||||
@ -66,7 +67,7 @@ const Wrapper = (props: PropsWithChildren<{ nodeProps: NodeProps }>) => {
|
||||
const handleMouseLeave = useCallback(() => {
|
||||
setIsHovering(false);
|
||||
}, []);
|
||||
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<NodeWrapper
|
||||
nodeId={props.nodeProps.id}
|
||||
@ -99,7 +100,7 @@ const Wrapper = (props: PropsWithChildren<{ nodeProps: NodeProps }>) => {
|
||||
_dark: { color: 'base.200' },
|
||||
}}
|
||||
>
|
||||
Current Image
|
||||
{t('nodes.currentImage')}
|
||||
</Text>
|
||||
</Flex>
|
||||
<Flex
|
||||
|
@ -4,8 +4,10 @@ import { useEmbedWorkflow } from 'features/nodes/hooks/useEmbedWorkflow';
|
||||
import { useWithWorkflow } from 'features/nodes/hooks/useWithWorkflow';
|
||||
import { nodeEmbedWorkflowChanged } from 'features/nodes/store/nodesSlice';
|
||||
import { ChangeEvent, memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const EmbedWorkflowCheckbox = ({ nodeId }: { nodeId: string }) => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const withWorkflow = useWithWorkflow(nodeId);
|
||||
const embedWorkflow = useEmbedWorkflow(nodeId);
|
||||
@ -27,7 +29,9 @@ const EmbedWorkflowCheckbox = ({ nodeId }: { nodeId: string }) => {
|
||||
|
||||
return (
|
||||
<FormControl as={Flex} sx={{ alignItems: 'center', gap: 2, w: 'auto' }}>
|
||||
<FormLabel sx={{ fontSize: 'xs', mb: '1px' }}>Workflow</FormLabel>
|
||||
<FormLabel sx={{ fontSize: 'xs', mb: '1px' }}>
|
||||
{t('metadata.workflow')}
|
||||
</FormLabel>
|
||||
<Checkbox
|
||||
className="nopan"
|
||||
size="sm"
|
||||
|
@ -75,7 +75,7 @@ const TooltipLabel = memo(({ nodeExecutionState }: TooltipLabelProps) => {
|
||||
const { status, progress, progressImage } = nodeExecutionState;
|
||||
const { t } = useTranslation();
|
||||
if (status === NodeStatus.PENDING) {
|
||||
return <Text>Pending</Text>;
|
||||
return <Text>{t('queue.pending')}</Text>;
|
||||
}
|
||||
if (status === NodeStatus.IN_PROGRESS) {
|
||||
if (progressImage) {
|
||||
|
@ -3,6 +3,7 @@ import { DRAG_HANDLE_CLASSNAME } from 'features/nodes/types/constants';
|
||||
import { memo } from 'react';
|
||||
import NodeCollapseButton from '../common/NodeCollapseButton';
|
||||
import NodeWrapper from '../common/NodeWrapper';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
type Props = {
|
||||
nodeId: string;
|
||||
@ -19,6 +20,7 @@ const InvocationNodeUnknownFallback = ({
|
||||
type,
|
||||
selected,
|
||||
}: Props) => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<NodeWrapper nodeId={nodeId} selected={selected}>
|
||||
<Flex
|
||||
@ -61,7 +63,7 @@ const InvocationNodeUnknownFallback = ({
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Text as="span">Unknown node type: </Text>
|
||||
<Text as="span">{t('nodes.unknownNodeType')}: </Text>
|
||||
<Text as="span" fontWeight={600}>
|
||||
{type}
|
||||
</Text>
|
||||
|
@ -4,8 +4,10 @@ import { useHasImageOutput } from 'features/nodes/hooks/useHasImageOutput';
|
||||
import { useIsIntermediate } from 'features/nodes/hooks/useIsIntermediate';
|
||||
import { nodeIsIntermediateChanged } from 'features/nodes/store/nodesSlice';
|
||||
import { ChangeEvent, memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const SaveToGalleryCheckbox = ({ nodeId }: { nodeId: string }) => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const hasImageOutput = useHasImageOutput(nodeId);
|
||||
const isIntermediate = useIsIntermediate(nodeId);
|
||||
@ -27,7 +29,9 @@ const SaveToGalleryCheckbox = ({ nodeId }: { nodeId: string }) => {
|
||||
|
||||
return (
|
||||
<FormControl as={Flex} sx={{ alignItems: 'center', gap: 2, w: 'auto' }}>
|
||||
<FormLabel sx={{ fontSize: 'xs', mb: '1px' }}>Save to Gallery</FormLabel>
|
||||
<FormLabel sx={{ fontSize: 'xs', mb: '1px' }}>
|
||||
{t('hotkeys.saveToGallery.title')}
|
||||
</FormLabel>
|
||||
<Checkbox
|
||||
className="nopan"
|
||||
size="sm"
|
||||
|
@ -3,6 +3,7 @@ import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { useUseCache } from 'features/nodes/hooks/useUseCache';
|
||||
import { nodeUseCacheChanged } from 'features/nodes/store/nodesSlice';
|
||||
import { ChangeEvent, memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const UseCacheCheckbox = ({ nodeId }: { nodeId: string }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
@ -18,10 +19,12 @@ const UseCacheCheckbox = ({ nodeId }: { nodeId: string }) => {
|
||||
},
|
||||
[dispatch, nodeId]
|
||||
);
|
||||
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<FormControl as={Flex} sx={{ alignItems: 'center', gap: 2, w: 'auto' }}>
|
||||
<FormLabel sx={{ fontSize: 'xs', mb: '1px' }}>Use Cache</FormLabel>
|
||||
<FormLabel sx={{ fontSize: 'xs', mb: '1px' }}>
|
||||
{t('invocationCache.useCache')}
|
||||
</FormLabel>
|
||||
<Checkbox
|
||||
className="nopan"
|
||||
size="sm"
|
||||
|
@ -79,7 +79,7 @@ const FieldContextMenu = ({ nodeId, fieldName, kind, children }: Props) => {
|
||||
icon={<FaPlus />}
|
||||
onClick={handleExposeField}
|
||||
>
|
||||
Add to Linear View
|
||||
{t('nodes.addLinearView')}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
@ -90,7 +90,7 @@ const FieldContextMenu = ({ nodeId, fieldName, kind, children }: Props) => {
|
||||
icon={<FaMinus />}
|
||||
onClick={handleUnexposeField}
|
||||
>
|
||||
Remove from Linear View
|
||||
{t('nodes.removeLinearView')}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
@ -102,6 +102,7 @@ const FieldContextMenu = ({ nodeId, fieldName, kind, children }: Props) => {
|
||||
isExposed,
|
||||
mayExpose,
|
||||
nodeId,
|
||||
t,
|
||||
]);
|
||||
|
||||
const renderMenuFunc = useCallback(
|
||||
|
@ -49,8 +49,16 @@ const FieldTooltipContent = ({ nodeId, fieldName, kind }: Props) => {
|
||||
{fieldTemplate.description}
|
||||
</Text>
|
||||
)}
|
||||
{fieldTemplate && <Text>Type: {FIELDS[fieldTemplate.type].title}</Text>}
|
||||
{isInputTemplate && <Text>Input: {startCase(fieldTemplate.input)}</Text>}
|
||||
{fieldTemplate && (
|
||||
<Text>
|
||||
{t('parameters.type')}: {FIELDS[fieldTemplate.type].title}
|
||||
</Text>
|
||||
)}
|
||||
{isInputTemplate && (
|
||||
<Text>
|
||||
{t('common.input')}: {startCase(fieldTemplate.input)}
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
@ -7,6 +7,7 @@ import EditableFieldTitle from './EditableFieldTitle';
|
||||
import FieldContextMenu from './FieldContextMenu';
|
||||
import FieldHandle from './FieldHandle';
|
||||
import InputFieldRenderer from './InputFieldRenderer';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface Props {
|
||||
nodeId: string;
|
||||
@ -14,6 +15,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const InputField = ({ nodeId, fieldName }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const fieldTemplate = useFieldTemplate(nodeId, fieldName, 'input');
|
||||
const doesFieldHaveValue = useDoesInputHaveValue(nodeId, fieldName);
|
||||
|
||||
@ -49,7 +51,7 @@ const InputField = ({ nodeId, fieldName }: Props) => {
|
||||
<FormControl
|
||||
sx={{ color: 'error.400', textAlign: 'left', fontSize: 'sm' }}
|
||||
>
|
||||
Unknown input: {fieldName}
|
||||
{t('nodes.unknownInput')}: {fieldName}
|
||||
</FormControl>
|
||||
</InputFieldWrapper>
|
||||
);
|
||||
|
@ -18,6 +18,7 @@ import VaeModelInputField from './inputs/VaeModelInputField';
|
||||
import IPAdapterModelInputField from './inputs/IPAdapterModelInputField';
|
||||
import T2IAdapterModelInputField from './inputs/T2IAdapterModelInputField';
|
||||
import BoardInputField from './inputs/BoardInputField';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
type InputFieldProps = {
|
||||
nodeId: string;
|
||||
@ -25,11 +26,16 @@ type InputFieldProps = {
|
||||
};
|
||||
|
||||
const InputFieldRenderer = ({ nodeId, fieldName }: InputFieldProps) => {
|
||||
const { t } = useTranslation();
|
||||
const field = useFieldData(nodeId, fieldName);
|
||||
const fieldTemplate = useFieldTemplate(nodeId, fieldName, 'input');
|
||||
|
||||
if (fieldTemplate?.fieldKind === 'output') {
|
||||
return <Box p={2}>Output field in input: {field?.type}</Box>;
|
||||
return (
|
||||
<Box p={2}>
|
||||
{t('nodes.outputFieldInInput')}: {field?.type}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
@ -249,7 +255,7 @@ const InputFieldRenderer = ({ nodeId, fieldName }: InputFieldProps) => {
|
||||
_dark: { color: 'error.300' },
|
||||
}}
|
||||
>
|
||||
Unknown field type: {field?.type}
|
||||
{t('nodes.unknownFieldType')}: {field?.type}
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
|
@ -5,6 +5,7 @@ import { HANDLE_TOOLTIP_OPEN_DELAY } from 'features/nodes/types/constants';
|
||||
import { PropsWithChildren, memo } from 'react';
|
||||
import FieldHandle from './FieldHandle';
|
||||
import FieldTooltipContent from './FieldTooltipContent';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface Props {
|
||||
nodeId: string;
|
||||
@ -12,6 +13,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const OutputField = ({ nodeId, fieldName }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const fieldTemplate = useFieldTemplate(nodeId, fieldName, 'output');
|
||||
|
||||
const {
|
||||
@ -28,7 +30,7 @@ const OutputField = ({ nodeId, fieldName }: Props) => {
|
||||
<FormControl
|
||||
sx={{ color: 'error.400', textAlign: 'right', fontSize: 'sm' }}
|
||||
>
|
||||
Unknown output: {fieldName}
|
||||
{t('nodes.unknownOutput')}: {fieldName}
|
||||
</FormControl>
|
||||
</OutputFieldWrapper>
|
||||
);
|
||||
|
@ -16,6 +16,7 @@ import {
|
||||
ImagePolymorphicInputFieldValue,
|
||||
} from 'features/nodes/types/types';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaUndo } from 'react-icons/fa';
|
||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||
import { PostUploadAction } from 'services/api/types';
|
||||
@ -103,18 +104,24 @@ const ImageInputFieldComponent = (
|
||||
|
||||
export default memo(ImageInputFieldComponent);
|
||||
|
||||
const UploadElement = memo(() => (
|
||||
<Text fontSize={16} fontWeight={600}>
|
||||
Drop or Upload
|
||||
</Text>
|
||||
));
|
||||
const UploadElement = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Text fontSize={16} fontWeight={600}>
|
||||
{t('gallery.dropOrUpload')}
|
||||
</Text>
|
||||
);
|
||||
});
|
||||
|
||||
UploadElement.displayName = 'UploadElement';
|
||||
|
||||
const DropLabel = memo(() => (
|
||||
<Text fontSize={16} fontWeight={600}>
|
||||
Drop
|
||||
</Text>
|
||||
));
|
||||
const DropLabel = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Text fontSize={16} fontWeight={600}>
|
||||
{t('gallery.drop')}
|
||||
</Text>
|
||||
);
|
||||
});
|
||||
|
||||
DropLabel.displayName = 'DropLabel';
|
||||
|
@ -91,7 +91,7 @@ const LoRAModelInputFieldComponent = (
|
||||
return (
|
||||
<Flex sx={{ justifyContent: 'center', p: 2 }}>
|
||||
<Text sx={{ fontSize: 'sm', color: 'base.500', _dark: 'base.700' }}>
|
||||
No LoRAs Loaded
|
||||
{t('models.noLoRAsLoaded')}
|
||||
</Text>
|
||||
</Flex>
|
||||
);
|
||||
|
@ -90,7 +90,7 @@ const Content = (props: {
|
||||
<EditableNodeTitle nodeId={props.node.data.id} />
|
||||
<HStack>
|
||||
<FormControl>
|
||||
<FormLabel>Node Type</FormLabel>
|
||||
<FormLabel>{t('nodes.nodeType')}</FormLabel>
|
||||
<Text fontSize="sm" fontWeight={600}>
|
||||
{props.template.title}
|
||||
</Text>
|
||||
@ -102,7 +102,7 @@ const Content = (props: {
|
||||
w="full"
|
||||
>
|
||||
<FormControl isInvalid={needsUpdate}>
|
||||
<FormLabel>Node Version</FormLabel>
|
||||
<FormLabel>{t('nodes.nodeVersion')}</FormLabel>
|
||||
<Text fontSize="sm" fontWeight={600}>
|
||||
{props.node.data.version}
|
||||
</Text>
|
||||
|
@ -10,6 +10,7 @@ import { memo, useCallback } from 'react';
|
||||
import { FaUndo, FaUpload } from 'react-icons/fa';
|
||||
import InitialImage from './InitialImage';
|
||||
import { PostUploadAction } from 'services/api/types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createSelector(
|
||||
[stateSelector],
|
||||
@ -38,6 +39,8 @@ const InitialImageDisplay = () => {
|
||||
dispatch(clearInitialImage());
|
||||
}, [dispatch]);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Flex
|
||||
layerStyle="first"
|
||||
@ -73,7 +76,7 @@ const InitialImageDisplay = () => {
|
||||
},
|
||||
}}
|
||||
>
|
||||
Initial Image
|
||||
{t('metadata.initImage')}
|
||||
</Text>
|
||||
<Spacer />
|
||||
<IAIIconButton
|
||||
|
@ -106,7 +106,7 @@ const QueueItemComponent = ({ queueItemDTO }: Props) => {
|
||||
flexDir="column"
|
||||
>
|
||||
<Heading size="sm" color="error.500" _dark={{ color: 'error.400' }}>
|
||||
Error
|
||||
{t('common.error')}
|
||||
</Heading>
|
||||
<pre>{queueItem.error}</pre>
|
||||
</Flex>
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* eslint-disable i18next/no-literal-string */
|
||||
|
||||
import { Flex, Image, Text } from '@chakra-ui/react';
|
||||
import InvokeAILogoImage from 'assets/images/logo.png';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
|
@ -423,7 +423,8 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
||||
<Flex justifyContent="center">
|
||||
<Text fontSize="lg">
|
||||
<Text>
|
||||
{t('settings.resetComplete')} Reloading in {countdown}...
|
||||
{t('settings.resetComplete')} {t('settings.reloadingIn')}{' '}
|
||||
{countdown}...
|
||||
</Text>
|
||||
</Text>
|
||||
</Flex>
|
||||
|
@ -3517,6 +3517,14 @@ eslint-config-prettier@^9.0.0:
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz#eb25485946dd0c66cd216a46232dc05451518d1f"
|
||||
integrity sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==
|
||||
|
||||
eslint-plugin-i18next@^6.0.3:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-i18next/-/eslint-plugin-i18next-6.0.3.tgz#a388f9982deb040102c1c4498e4dc38d9bd6ffd9"
|
||||
integrity sha512-RtQXYfg6PZCjejIQ/YG+dUj/x15jPhufJ9hUDGH0kCpJ6CkVMAWOQ9exU1CrbPmzeykxLjrXkjAaOZF/V7+DOA==
|
||||
dependencies:
|
||||
lodash "^4.17.21"
|
||||
requireindex "~1.1.0"
|
||||
|
||||
eslint-plugin-react-hooks@^4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3"
|
||||
@ -5617,6 +5625,11 @@ require-directory@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
|
||||
integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
|
||||
|
||||
requireindex@~1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.1.0.tgz#e5404b81557ef75db6e49c5a72004893fe03e162"
|
||||
integrity sha512-LBnkqsDE7BZKvqylbmn7lTIVdpx4K/QCduRATpO5R+wtPmky/a8pN1bO2D6wXppn1497AJF9mNjqAXr6bdl9jg==
|
||||
|
||||
requirejs-config-file@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/requirejs-config-file/-/requirejs-config-file-4.0.0.tgz#4244da5dd1f59874038cc1091d078d620abb6ebc"
|
||||
|
Loading…
Reference in New Issue
Block a user