Compare commits

..

31 Commits

Author SHA1 Message Date
Lincoln Stein
060eff5dad bump rc version 2022-12-28 20:37:36 -05:00
Lincoln Stein
5d00831f71 Merge branch 'main' into lstein-release-candidate-2-2-5 2022-12-28 20:33:39 -05:00
blessedcoolant
a029d90630 Model Manager Final Build 2022-12-29 08:33:27 +13:00
blessedcoolant
211d6b3831 Improve add models guidance 2022-12-29 08:33:27 +13:00
blessedcoolant
b40faa98bd Model Manager Test Build 4 2022-12-29 08:33:27 +13:00
blessedcoolant
8d4ad0de4e Formatting Pass 2022-12-29 08:33:27 +13:00
blessedcoolant
e4b2f815e8 Improve interaction area for edit and stylize 2022-12-29 08:33:27 +13:00
blessedcoolant
0dd5804949 Normalize the config path to prevent write errors 2022-12-29 08:33:27 +13:00
blessedcoolant
53476af72e Add Italian and PT BR Localization for Model Manager 2022-12-29 08:33:27 +13:00
blessedcoolant
61ee597f4b Add Messages To Indicate to the user to add models. 2022-12-29 08:33:27 +13:00
blessedcoolant
ad0b366e47 Add option to scan loaded folder again 2022-12-29 08:33:27 +13:00
blessedcoolant
942f029a24 Model Manager Test Build 3 2022-12-29 08:33:27 +13:00
blessedcoolant
e0d7c466cc Add Scrollbar Styling 2022-12-29 08:33:27 +13:00
blessedcoolant
16c0132a6b Model Manager Test Build 2 2022-12-29 08:33:27 +13:00
blessedcoolant
7cb2fcf8b4 Remove folder picker 2022-12-29 08:33:27 +13:00
blessedcoolant
1a65d43569 Add Icon To the tkinter folder picker 2022-12-29 08:33:27 +13:00
blessedcoolant
1313e31f62 Add Italian Localization for Model Manager 2022-12-29 08:33:27 +13:00
blessedcoolant
aa213285bb Style fixes to accommodate localization in Model Manager 2022-12-29 08:33:27 +13:00
blessedcoolant
f691353570 Add Model Manager German Localization 2022-12-29 08:33:27 +13:00
blessedcoolant
1c75010f29 Model Manager Test Build 2022-12-29 08:33:27 +13:00
blessedcoolant
eba8fb58ed Change Settings Icon in the Site Header 2022-12-29 08:33:27 +13:00
blessedcoolant
83a7e60fe5 Add Missing Localization Files for Model Manager 2022-12-29 08:33:27 +13:00
blessedcoolant
d4e86feeeb Add Simplified Chinese Localization
Co-Authored-By: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
2022-12-29 08:33:27 +13:00
blessedcoolant
427614d1df Populate en-US localization configs 2022-12-29 08:33:27 +13:00
blessedcoolant
ce6fb8ea29 Model Form Styling 2022-12-29 08:33:27 +13:00
blessedcoolant
df858eb3f9 Add Edit Model Functionality 2022-12-29 08:33:27 +13:00
blessedcoolant
6523fd07ab Model Edit Initial Implementation 2022-12-29 08:33:27 +13:00
Kent Keirsey
a823e37126 Fix storehook references 2022-12-29 08:33:27 +13:00
Kent Keirsey
4eed06903c Adding model edits (unstable/WIP) 2022-12-29 08:33:27 +13:00
blessedcoolant
79d577bff9 Model Manager Frontend Rebased 2022-12-29 08:33:27 +13:00
blessedcoolant
3521557541 Model Manager Backend Implementation 2022-12-29 08:33:27 +13:00
92 changed files with 4762 additions and 941 deletions

View File

@@ -17,10 +17,12 @@ from PIL import Image, ImageOps
from PIL.Image import Image as ImageType
from uuid import uuid4
from threading import Event
from tkinter import filedialog
from ldm.generate import Generate
from ldm.invoke.args import Args, APP_ID, APP_VERSION, calculate_init_img_hash
from ldm.invoke.conditioning import get_tokens_for_prompt, get_prompt_structure
from ldm.invoke.globals import Globals
from ldm.invoke.pngwriter import PngWriter, retrieve_metadata
from ldm.invoke.prompt_parser import split_weighted_subprompts, Blend
from ldm.invoke.generator.inpaint import infill_methods
@@ -39,6 +41,9 @@ args.root_dir = os.path.expanduser(args.root_dir or "..")
if not os.path.isabs(args.outdir):
args.outdir = os.path.join(args.root_dir, args.outdir)
# normalize the config directory relative to root
if not os.path.isabs(opt.conf):
opt.conf = os.path.normpath(os.path.join(Globals.root,opt.conf))
class InvokeAIWebServer:
def __init__(self, generate: Generate, gfpgan, codeformer, esrgan) -> None:
@@ -297,6 +302,78 @@ class InvokeAIWebServer:
config["infill_methods"] = infill_methods()
socketio.emit("systemConfig", config)
@socketio.on('searchForModels')
def handle_search_models(search_folder: str):
try:
if not search_folder:
socketio.emit(
"foundModels",
{'search_folder': None, 'found_models': None},
)
else:
search_folder, found_models = self.generate.model_cache.search_models(search_folder)
socketio.emit(
"foundModels",
{'search_folder': search_folder, 'found_models': found_models},
)
except Exception as e:
self.socketio.emit("error", {"message": (str(e))})
print("\n")
traceback.print_exc()
print("\n")
@socketio.on("addNewModel")
def handle_add_model(new_model_config: dict):
try:
model_name = new_model_config['name']
del new_model_config['name']
model_attributes = new_model_config
update = False
current_model_list = self.generate.model_cache.list_models()
if model_name in current_model_list:
update = True
print(f">> Adding New Model: {model_name}")
self.generate.model_cache.add_model(
model_name=model_name, model_attributes=model_attributes, clobber=True)
self.generate.model_cache.commit(opt.conf)
new_model_list = self.generate.model_cache.list_models()
socketio.emit(
"newModelAdded",
{"new_model_name": model_name,
"model_list": new_model_list, 'update': update},
)
print(f">> New Model Added: {model_name}")
except Exception as e:
self.socketio.emit("error", {"message": (str(e))})
print("\n")
traceback.print_exc()
print("\n")
@socketio.on("deleteModel")
def handle_delete_model(model_name: str):
try:
print(f">> Deleting Model: {model_name}")
self.generate.model_cache.del_model(model_name)
self.generate.model_cache.commit(opt.conf)
updated_model_list = self.generate.model_cache.list_models()
socketio.emit(
"modelDeleted",
{"deleted_model_name": model_name,
"model_list": updated_model_list},
)
print(f">> Model Deleted: {model_name}")
except Exception as e:
self.socketio.emit("error", {"message": (str(e))})
print("\n")
traceback.print_exc()
print("\n")
@socketio.on("requestModelChange")
def handle_set_model(model_name: str):
try:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

625
frontend/dist/assets/index.21ff81eb.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -7,8 +7,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>InvokeAI - A Stable Diffusion Toolkit</title>
<link rel="shortcut icon" type="icon" href="./assets/favicon.0d253ced.ico" />
<script type="module" crossorigin src="./assets/index.6acd2bd4.js"></script>
<link rel="stylesheet" href="./assets/index.25b49ba2.css">
<script type="module" crossorigin src="./assets/index.21ff81eb.js"></script>
<link rel="stylesheet" href="./assets/index.0dadf5d0.css">
<script type="module">try{import.meta.url;import("_").catch(()=>1);}catch(e){}window.__vite_is_modern_browser=true;</script>
<script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy build because dynamic import or import.meta.url is unsupported, syntax error above should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script>
</head>
@@ -18,6 +18,6 @@
<script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
<script nomodule crossorigin id="vite-legacy-polyfill" src="./assets/polyfills-legacy-dde3a68a.js"></script>
<script nomodule crossorigin id="vite-legacy-entry" data-src="./assets/index-legacy-4585c87a.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
<script nomodule crossorigin id="vite-legacy-entry" data-src="./assets/index-legacy-b741077f.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
</body>
</html>

View File

@@ -1,3 +1,56 @@
{
"hotkeysLabel": "Hotkeys"
"hotkeysLabel": "Hotkeys",
"themeLabel": "Theme",
"languagePickerLabel": "Language Picker",
"reportBugLabel": "Report Bug",
"githubLabel": "Github",
"discordLabel": "Discord",
"settingsLabel": "Settings",
"darkTheme": "Dark",
"lightTheme": "Light",
"greenTheme": "Green",
"langEnglish": "English",
"langRussian": "Russian",
"langItalian": "Italian",
"langBrPortuguese": "Portuguese (Brazilian)",
"langGerman": "German",
"langPortuguese": "Portuguese",
"langFrench": "French",
"langPolish": "Polish",
"text2img": "Text To Image",
"img2img": "Image To Image",
"unifiedCanvas": "Unified Canvas",
"nodes": "Nodes",
"nodesDesc": "A node based system for the generation of images is under development currently. Stay tuned for updates about this amazing feature.",
"postProcessing": "Post Processing",
"postProcessDesc1": "Invoke AI offers a wide variety of post processing features. Image Upscaling and Face Restoration are already available in the WebUI. You can access them from the Advanced Options menu of the Text To Image and Image To Image tabs. You can also process images directly, using the image action buttons above the current image display or in the viewer.",
"postProcessDesc2": "A dedicated UI will be released soon to facilitate more advanced post processing workflows.",
"postProcessDesc3": "The Invoke AI Command Line Interface offers various other features including Embiggen.",
"training": "Training",
"trainingDesc1": "A dedicated workflow for training your own embeddings and checkpoints using Textual Inversion and Dreambooth from the web interface.",
"trainingDesc2": "InvokeAI already supports training custom embeddings using Textual Inversion using the main script.",
"upload": "Upload",
"close": "Close",
"load": "Load",
"statusConnected": "Connected",
"statusDisconnected": "Disconnected",
"statusError": "Error",
"statusPreparing": "Preparing",
"statusProcessingCanceled": "Processing Canceled",
"statusProcessingComplete": "Processing Complete",
"statusGenerating": "Generating",
"statusGeneratingTextToImage": "Generating Text To Image",
"statusGeneratingImageToImage": "Generating Image To Image",
"statusGeneratingInpainting": "Generating Inpainting",
"statusGeneratingOutpainting": "Generating Outpainting",
"statusGenerationComplete": "Generation Complete",
"statusIterationComplete": "Iteration Complete",
"statusSavingImage": "Saving Image",
"statusRestoringFaces": "Restoring Faces",
"statusRestoringFacesGFPGAN": "Restoring Faces (GFPGAN)",
"statusRestoringFacesCodeFormer": "Restoring Faces (CodeFormer)",
"statusUpscaling": "Upscaling",
"statusUpscalingESRGAN": "Upscaling (ESRGAN)",
"statusLoadingModel": "Loading Model",
"statusModelChanged": "Model Changed"
}

View File

@@ -17,6 +17,7 @@
"langPortuguese": "Portuguese",
"langFrench": "French",
"langPolish": "Polish",
"langSimplifiedChinese": "Simplified Chinese",
"text2img": "Text To Image",
"img2img": "Image To Image",
"unifiedCanvas": "Unified Canvas",

View File

@@ -17,6 +17,7 @@
"langPortuguese": "Portoghese",
"langFrench": "Francese",
"langPolish": "Polacco",
"langSimplifiedChinese": "Cinese semplificato",
"text2img": "Testo a Immagine",
"img2img": "Immagine a Immagine",
"unifiedCanvas": "Tela unificata",

54
frontend/dist/locales/common/zh_cn.json vendored Normal file
View File

@@ -0,0 +1,54 @@
{
"hotkeysLabel": "快捷键",
"themeLabel": "主题",
"languagePickerLabel": "语言",
"reportBugLabel": "提交错误报告",
"githubLabel": "GitHub",
"discordLabel": "Discord",
"settingsLabel": "设置",
"darkTheme": "暗色",
"lightTheme": "亮色",
"greenTheme": "绿色",
"langEnglish": "英语",
"langRussian": "俄语",
"langItalian": "意大利语",
"langPortuguese": "葡萄牙语",
"langFrench": "法语",
"langChineseSimplified": "简体中文",
"text2img": "文字到图像",
"img2img": "图像到图像",
"unifiedCanvas": "统一画布",
"nodes": "节点",
"nodesDesc": "一个基于节点的图像生成系统目前正在开发中。请持续关注关于这一功能的更新。",
"postProcessing": "后期处理",
"postProcessDesc1": "Invoke AI 提供各种各样的后期处理功能。图像放大和面部修复在网页界面中已经可用。你可以从文本到图像和图像到图像页面的高级选项菜单中访问它们。你也可以直接使用图像显示上方或查看器中的图像操作按钮处理图像。",
"postProcessDesc2": "一个专门的界面将很快发布,新的界面能够处理更复杂的后期处理流程。",
"postProcessDesc3": "Invoke AI 命令行界面提供例如Embiggen的各种其他功能。",
"training": "训练",
"trainingDesc1": "一个专门用于从网络UI使用Textual Inversion和Dreambooth训练自己的嵌入模型和检查点的工作流程。",
"trainingDesc2": "InvokeAI已经支持使用主脚本中的Textual Inversion来训练自定义的嵌入模型。",
"upload": "上传",
"close": "关闭",
"load": "加载",
"statusConnected": "已连接",
"statusDisconnected": "未连接",
"statusError": "错误",
"statusPreparing": "准备中",
"statusProcessingCanceled": "处理取消",
"statusProcessingComplete": "处理完成",
"statusGenerating": "生成中",
"statusGeneratingTextToImage": "文字到图像生成中",
"statusGeneratingImageToImage": "图像到图像生成中",
"statusGeneratingInpainting": "生成内画中",
"statusGeneratingOutpainting": "生成外画中",
"statusGenerationComplete": "生成完成",
"statusIterationComplete": "迭代完成",
"statusSavingImage": "图像保存中",
"statusRestoringFaces": "脸部修复中",
"statusRestoringFacesGFPGAN": "脸部修复中 (GFPGAN)",
"statusRestoringFacesCodeFormer": "脸部修复中 (CodeFormer)",
"statusUpscaling": "放大中",
"statusUpscalingESRGAN": "放大中 (ESRGAN)",
"statusLoadingModel": "模型加载中",
"statusModelChanged": "模型已切换"
}

View File

@@ -1 +1,16 @@
{}
{
"generations": "Generations",
"showGenerations": "Show Generations",
"uploads": "Uploads",
"showUploads": "Show Uploads",
"galleryImageSize": "Image Size",
"galleryImageResetSize": "Reset Size",
"gallerySettings": "Gallery Settings",
"maintainAspectRatio": "Maintain Aspect Ratio",
"autoSwitchNewImages": "Auto-Switch to New Images",
"singleColumnLayout": "Single Column Layout",
"pinGallery": "Pin Gallery",
"allImagesLoaded": "All Images Loaded",
"loadMore": "Load More",
"noImagesInGallery": "No Images In Gallery"
}

View File

@@ -0,0 +1,16 @@
{
"generations": "生成的图像",
"showGenerations": "显示生成的图像",
"uploads": "上传的图像",
"showUploads": "显示上传的图像",
"galleryImageSize": "预览大小",
"galleryImageResetSize": "重置预览大小",
"gallerySettings": "预览设置",
"maintainAspectRatio": "保持比例",
"autoSwitchNewImages": "自动切换到新图像",
"singleColumnLayout": "单列布局",
"pinGallery": "保持图库常开",
"allImagesLoaded": "所有图像加载完成",
"loadMore": "加载更多",
"noImagesInGallery": "图库中无图像"
}

View File

@@ -1 +1,207 @@
{}
{
"keyboardShortcuts": "Keyboard Shorcuts",
"appHotkeys": "App Hotkeys",
"generalHotkeys": "General Hotkeys",
"galleryHotkeys": "Gallery Hotkeys",
"unifiedCanvasHotkeys": "Unified Canvas Hotkeys",
"invoke": {
"title": "Invoke",
"desc": "Generate an image"
},
"cancel": {
"title": "Cancel",
"desc": "Cancel image generation"
},
"focusPrompt": {
"title": "Focus Prompt",
"desc": "Focus the prompt input area"
},
"toggleOptions": {
"title": "Toggle Options",
"desc": "Open and close the options panel"
},
"pinOptions": {
"title": "Pin Options",
"desc": "Pin the options panel"
},
"toggleViewer": {
"title": "Toggle Viewer",
"desc": "Open and close Image Viewer"
},
"toggleGallery": {
"title": "Toggle Gallery",
"desc": "Open and close the gallery drawer"
},
"maximizeWorkSpace": {
"title": "Maximize Workspace",
"desc": "Close panels and maximize work area"
},
"changeTabs": {
"title": "Change Tabs",
"desc": "Switch to another workspace"
},
"consoleToggle": {
"title": "Console Toggle",
"desc": "Open and close console"
},
"setPrompt": {
"title": "Set Prompt",
"desc": "Use the prompt of the current image"
},
"setSeed": {
"title": "Set Seed",
"desc": "Use the seed of the current image"
},
"setParameters": {
"title": "Set Parameters",
"desc": "Use all parameters of the current image"
},
"restoreFaces": {
"title": "Restore Faces",
"desc": "Restore the current image"
},
"upscale": {
"title": "Upscale",
"desc": "Upscale the current image"
},
"showInfo": {
"title": "Show Info",
"desc": "Show metadata info of the current image"
},
"sendToImageToImage": {
"title": "Send To Image To Image",
"desc": "Send current image to Image to Image"
},
"deleteImage": {
"title": "Delete Image",
"desc": "Delete the current image"
},
"closePanels": {
"title": "Close Panels",
"desc": "Closes open panels"
},
"previousImage": {
"title": "Previous Image",
"desc": "Display the previous image in gallery"
},
"nextImage": {
"title": "Next Image",
"desc": "Display the next image in gallery"
},
"toggleGalleryPin": {
"title": "Toggle Gallery Pin",
"desc": "Pins and unpins the gallery to the UI"
},
"increaseGalleryThumbSize": {
"title": "Increase Gallery Image Size",
"desc": "Increases gallery thumbnails size"
},
"decreaseGalleryThumbSize": {
"title": "Decrease Gallery Image Size",
"desc": "Decreases gallery thumbnails size"
},
"selectBrush": {
"title": "Select Brush",
"desc": "Selects the canvas brush"
},
"selectEraser": {
"title": "Select Eraser",
"desc": "Selects the canvas eraser"
},
"decreaseBrushSize": {
"title": "Decrease Brush Size",
"desc": "Decreases the size of the canvas brush/eraser"
},
"increaseBrushSize": {
"title": "Increase Brush Size",
"desc": "Increases the size of the canvas brush/eraser"
},
"decreaseBrushOpacity": {
"title": "Decrease Brush Opacity",
"desc": "Decreases the opacity of the canvas brush"
},
"increaseBrushOpacity": {
"title": "Increase Brush Opacity",
"desc": "Increases the opacity of the canvas brush"
},
"moveTool": {
"title": "Move Tool",
"desc": "Allows canvas navigation"
},
"fillBoundingBox": {
"title": "Fill Bounding Box",
"desc": "Fills the bounding box with brush color"
},
"eraseBoundingBox": {
"title": "Erase Bounding Box",
"desc": "Erases the bounding box area"
},
"colorPicker": {
"title": "Select Color Picker",
"desc": "Selects the canvas color picker"
},
"toggleSnap": {
"title": "Toggle Snap",
"desc": "Toggles Snap to Grid"
},
"quickToggleMove": {
"title": "Quick Toggle Move",
"desc": "Temporarily toggles Move mode"
},
"toggleLayer": {
"title": "Toggle Layer",
"desc": "Toggles mask/base layer selection"
},
"clearMask": {
"title": "Clear Mask",
"desc": "Clear the entire mask"
},
"hideMask": {
"title": "Hide Mask",
"desc": "Hide and unhide mask"
},
"showHideBoundingBox": {
"title": "Show/Hide Bounding Box",
"desc": "Toggle visibility of bounding box"
},
"mergeVisible": {
"title": "Merge Visible",
"desc": "Merge all visible layers of canvas"
},
"saveToGallery": {
"title": "Save To Gallery",
"desc": "Save current canvas to gallery"
},
"copyToClipboard": {
"title": "Copy to Clipboard",
"desc": "Copy current canvas to clipboard"
},
"downloadImage": {
"title": "Download Image",
"desc": "Download current canvas"
},
"undoStroke": {
"title": "Undo Stroke",
"desc": "Undo a brush stroke"
},
"redoStroke": {
"title": "Redo Stroke",
"desc": "Redo a brush stroke"
},
"resetView": {
"title": "Reset View",
"desc": "Reset Canvas View"
},
"previousStagingImage": {
"title": "Previous Staging Image",
"desc": "Previous Staging Area Image"
},
"nextStagingImage": {
"title": "Next Staging Image",
"desc": "Next Staging Area Image"
},
"acceptStagingImage": {
"title": "Accept Staging Image",
"desc": "Accept Current Staging Area Image"
}
}

207
frontend/dist/locales/hotkeys/zh_cn.json vendored Normal file
View File

@@ -0,0 +1,207 @@
{
"keyboardShortcuts": "快捷方式",
"appHotkeys": "应用快捷方式",
"generalHotkeys": "一般快捷方式",
"galleryHotkeys": "图库快捷方式",
"unifiedCanvasHotkeys": "统一画布快捷方式",
"invoke": {
"title": "Invoke",
"desc": "生成图像"
},
"cancel": {
"title": "取消",
"desc": "取消图像生成"
},
"focusPrompt": {
"title": "打开提示框",
"desc": "打开提示文本框"
},
"toggleOptions": {
"title": "切换选项卡",
"desc": "打开或关闭选项卡"
},
"pinOptions": {
"title": "常开选项卡",
"desc": "保持选项卡常开"
},
"toggleViewer": {
"title": "切换图像视图",
"desc": "打开或关闭图像视图"
},
"toggleGallery": {
"title": "切换图库",
"desc": "打开或关闭图库"
},
"maximizeWorkSpace": {
"title": "工作台最大化",
"desc": "关闭所有浮窗,将工作区域最大化"
},
"changeTabs": {
"title": "切换卡片",
"desc": "切换到另一个工作区"
},
"consoleToggle": {
"title": "切换命令行",
"desc": "打开或关闭命令行"
},
"setPrompt": {
"title": "使用提示",
"desc": "使用当前图像的提示词"
},
"setSeed": {
"title": "使用种子",
"desc": "使用当前图像的种子"
},
"setParameters": {
"title": "使用所有参数",
"desc": "使用当前图像的所有参数"
},
"restoreFaces": {
"title": "脸部修复",
"desc": "对当前图像进行脸部修复"
},
"upscale": {
"title": "放大",
"desc": "对当前图像进行放大"
},
"showInfo": {
"title": "显示信息",
"desc": "显示当前图像的元数据"
},
"sendToImageToImage": {
"title": "送往图像到图像",
"desc": "将当前图像送往图像到图像"
},
"deleteImage": {
"title": "删除图像",
"desc": "删除当前图像"
},
"closePanels": {
"title": "关闭浮窗",
"desc": "关闭目前打开的浮窗"
},
"previousImage": {
"title": "上一张图像",
"desc": "显示相册中的上一张图像"
},
"nextImage": {
"title": "下一张图像",
"desc": "显示相册中的下一张图像"
},
"toggleGalleryPin": {
"title": "切换图库常开",
"desc": "开关图库在界面中的常开模式"
},
"increaseGalleryThumbSize": {
"title": "增大预览大小",
"desc": "增大图库中预览的大小"
},
"decreaseGalleryThumbSize": {
"title": "减小预览大小",
"desc": "减小图库中预览的大小"
},
"selectBrush": {
"title": "选择刷子",
"desc": "选择统一画布上的刷子"
},
"selectEraser": {
"title": "选择橡皮擦",
"desc": "选择统一画布上的橡皮擦"
},
"decreaseBrushSize": {
"title": "减小刷子大小",
"desc": "减小统一画布上的刷子或橡皮擦的大小"
},
"increaseBrushSize": {
"title": "增大刷子大小",
"desc": "增大统一画布上的刷子或橡皮擦的大小"
},
"decreaseBrushOpacity": {
"title": "减小刷子不透明度",
"desc": "减小统一画布上的刷子的不透明度"
},
"increaseBrushOpacity": {
"title": "增大刷子不透明度",
"desc": "增大统一画布上的刷子的不透明度"
},
"moveTool": {
"title": "移动工具",
"desc": "在画布上移动"
},
"fillBoundingBox": {
"title": "填充选择区域",
"desc": "在选择区域中填充刷子颜色"
},
"eraseBoundingBox": {
"title": "取消选择区域",
"desc": "将选择区域抹除"
},
"colorPicker": {
"title": "颜色提取工具",
"desc": "选择颜色提取工具"
},
"toggleSnap": {
"title": "切换网格对齐",
"desc": "打开或关闭网格对齐"
},
"quickToggleMove": {
"title": "快速切换移动模式",
"desc": "临时性地切换移动模式"
},
"toggleLayer": {
"title": "切换图层",
"desc": "切换遮罩/基础层的选择"
},
"clearMask": {
"title": "清除遮罩",
"desc": "清除整个遮罩层"
},
"hideMask": {
"title": "隐藏遮罩",
"desc": "隐藏或显示遮罩"
},
"showHideBoundingBox": {
"title": "显示/隐藏框选区",
"desc": "切换框选区的的显示状态"
},
"mergeVisible": {
"title": "合并可见层",
"desc": "将画板上可见层合并"
},
"saveToGallery": {
"title": "保存至图库",
"desc": "将画板当前内容保存至图库"
},
"copyToClipboard": {
"title": "复制到剪贴板",
"desc": "将画板当前内容复制到剪贴板"
},
"downloadImage": {
"title": "下载图像",
"desc": "下载画板当前内容"
},
"undoStroke": {
"title": "撤销画笔",
"desc": "撤销上一笔刷子的动作"
},
"redoStroke": {
"title": "重做画笔",
"desc": "重做上一笔刷子的动作"
},
"resetView": {
"title": "重置视图",
"desc": "重置画板视图"
},
"previousStagingImage": {
"title": "上一张暂存图像",
"desc": "上一张暂存区中的图像"
},
"nextStagingImage": {
"title": "下一张暂存图像",
"desc": "下一张暂存区中的图像"
},
"acceptStagingImage": {
"title": "接受暂存图像",
"desc": "接受当前暂存区中的图像"
}
}

View File

@@ -0,0 +1,50 @@
{
"modelManager": "Model Manager",
"model": "Model",
"modelAdded": "Model hinzugefügt",
"modelUpdated": "Model aktualisiert",
"modelEntryDeleted": "Modelleintrag gelöscht",
"cannotUseSpaces": "Leerzeichen können nicht verwendet werden",
"addNew": "Neue hinzufügen",
"addNewModel": "Neues Model hinzufügen",
"addManually": "Manuell hinzufügen",
"manual": "Manual",
"name": "Name",
"nameValidationMsg": "Geben Sie einen Namen für Ihr Model ein",
"description": "Beschreibung",
"descriptionValidationMsg": "Fügen Sie eine Beschreibung für Ihr Model hinzu",
"config": "Konfiguration",
"configValidationMsg": "Pfad zur Konfigurationsdatei Ihres Models.",
"modelLocation": "Ort des Models",
"modelLocationValidationMsg": "Pfad zum Speicherort Ihres Models.",
"vaeLocation": "VAE Ort",
"vaeLocationValidationMsg": "Pfad zum Speicherort Ihres VAE.",
"width": "Breite",
"widthValidationMsg": "Standardbreite Ihres Models.",
"height": "Höhe",
"heightValidationMsg": "Standardbhöhe Ihres Models.",
"addModel": "Model hinzufügen",
"updateModel": "Model aktualisieren",
"availableModels": "Verfügbare Models",
"search": "Suche",
"load": "Laden",
"active": "Aktiv",
"notLoaded": "nicht geladen",
"cached": "zwischengespeichert",
"checkpointFolder": "Checkpoint-Ordner",
"clearCheckpointFolder": "Checkpoint-Ordner löschen",
"findModels": "Models finden",
"modelsFound": "Models gefunden",
"selectFolder": "Ordner auswählen",
"selected": "Ausgewählt",
"selectAll": "Alles auswählen",
"deselectAll": "Alle abwählen",
"showExisting": "Vorhandene anzeigen",
"addSelected": "Auswahl hinzufügen",
"modelExists": "Model existiert",
"delete": "Löschen",
"deleteModel": "Model löschen",
"deleteConfig": "Konfiguration löschen",
"deleteMsg1": "Möchten Sie diesen Model-Eintrag wirklich aus InvokeAI löschen?",
"deleteMsg2": "Dadurch wird die Modellprüfpunktdatei nicht von Ihrer Festplatte gelöscht. Sie können sie bei Bedarf erneut hinzufügen."
}

View File

@@ -0,0 +1,50 @@
{
"modelManager": "Model Manager",
"model": "Model",
"modelAdded": "Model Added",
"modelUpdated": "Model Updated",
"modelEntryDeleted": "Model Entry Deleted",
"cannotUseSpaces": "Cannot Use Spaces",
"addNew": "Add New",
"addNewModel": "Add New Model",
"addManually": "Add Manually",
"manual": "Manual",
"name": "Name",
"nameValidationMsg": "Enter a name for your model",
"description": "Description",
"descriptionValidationMsg": "Add a description for your model",
"config": "Config",
"configValidationMsg": "Path to the config file of your model.",
"modelLocation": "Model Location",
"modelLocationValidationMsg": "Path to where your model is located.",
"vaeLocation": "VAE Location",
"vaeLocationValidationMsg": "Path to where your VAE is located.",
"width": "Width",
"widthValidationMsg": "Default width of your model.",
"height": "Height",
"heightValidationMsg": "Default height of your model.",
"addModel": "Add Model",
"updateModel": "Update Model",
"availableModels": "Available Models",
"search": "Search",
"load": "Load",
"active": "active",
"notLoaded": "not loaded",
"cached": "cached",
"checkpointFolder": "Checkpoint Folder",
"clearCheckpointFolder": "Clear Checkpoint Folder",
"findModels": "Find Models",
"modelsFound": "Models Found",
"selectFolder": "Select Folder",
"selected": "Selected",
"selectAll": "Select All",
"deselectAll": "Deselect All",
"showExisting": "Show Existing",
"addSelected": "Add Selected",
"modelExists": "Model Exists",
"delete": "Delete",
"deleteModel": "Delete Model",
"deleteConfig": "Delete Config",
"deleteMsg1": "Are you sure you want to delete this model entry from InvokeAI?",
"deleteMsg2": "This will not delete the model checkpoint file from your disk. You can readd them if you wish to."
}

View File

@@ -0,0 +1,53 @@
{
"modelManager": "Model Manager",
"model": "Model",
"modelAdded": "Model Added",
"modelUpdated": "Model Updated",
"modelEntryDeleted": "Model Entry Deleted",
"cannotUseSpaces": "Cannot Use Spaces",
"addNew": "Add New",
"addNewModel": "Add New Model",
"addManually": "Add Manually",
"manual": "Manual",
"name": "Name",
"nameValidationMsg": "Enter a name for your model",
"description": "Description",
"descriptionValidationMsg": "Add a description for your model",
"config": "Config",
"configValidationMsg": "Path to the config file of your model.",
"modelLocation": "Model Location",
"modelLocationValidationMsg": "Path to where your model is located.",
"vaeLocation": "VAE Location",
"vaeLocationValidationMsg": "Path to where your VAE is located.",
"width": "Width",
"widthValidationMsg": "Default width of your model.",
"height": "Height",
"heightValidationMsg": "Default height of your model.",
"addModel": "Add Model",
"updateModel": "Update Model",
"availableModels": "Available Models",
"search": "Search",
"load": "Load",
"active": "active",
"notLoaded": "not loaded",
"cached": "cached",
"checkpointFolder": "Checkpoint Folder",
"clearCheckpointFolder": "Clear Checkpoint Folder",
"findModels": "Find Models",
"scanAgain": "Scan Again",
"modelsFound": "Models Found",
"selectFolder": "Select Folder",
"selected": "Selected",
"selectAll": "Select All",
"deselectAll": "Deselect All",
"showExisting": "Show Existing",
"addSelected": "Add Selected",
"modelExists": "Model Exists",
"selectAndAdd": "Select and Add Models Listed Below",
"noModelsFound": "No Models Found",
"delete": "Delete",
"deleteModel": "Delete Model",
"deleteConfig": "Delete Config",
"deleteMsg1": "Are you sure you want to delete this model entry from InvokeAI?",
"deleteMsg2": "This will not delete the model checkpoint file from your disk. You can readd them if you wish to."
}

View File

@@ -0,0 +1,53 @@
{
"modelManager": "Gestione Modelli",
"model": "Modello",
"modelAdded": "Modello Aggiunto",
"modelUpdated": "Modello Aggiornato",
"modelEntryDeleted": "Modello Rimosso",
"cannotUseSpaces": "Impossibile utilizzare gli spazi",
"addNew": "Aggiungi nuovo",
"addNewModel": "Aggiungi nuovo Modello",
"addManually": "Aggiungi manualmente",
"manual": "Manuale",
"name": "Nome",
"nameValidationMsg": "Inserisci un nome per il modello",
"description": "Descrizione",
"descriptionValidationMsg": "Aggiungi una descrizione per il modello",
"config": "Config",
"configValidationMsg": "Percorso del file di configurazione del modello.",
"modelLocation": "Posizione del modello",
"modelLocationValidationMsg": "Percorso dove si trova il modello.",
"vaeLocation": "Posizione file VAE",
"vaeLocationValidationMsg": "Percorso dove si trova il file VAE.",
"width": "Larghezza",
"widthValidationMsg": "Larghezza predefinita del modello.",
"height": "Altezza",
"heightValidationMsg": "Altezza predefinita del modello.",
"addModel": "Aggiungi modello",
"updateModel": "Aggiorna modello",
"availableModels": "Modelli disponibili",
"search": "Ricerca",
"load": "Carica",
"active": "attivo",
"notLoaded": "non caricato",
"cached": "memorizzato nella cache",
"checkpointFolder": "Cartella Checkpoint",
"clearCheckpointFolder": "Svuota cartella checkpoint",
"findModels": "Trova modelli",
"scanAgain": "Scansiona nuovamente",
"modelsFound": "Modelli trovati",
"selectFolder": "Seleziona cartella",
"selected": "Selezionato",
"selectAll": "Seleziona tutto",
"deselectAll": "Deseleziona tutto",
"showExisting": "Mostra esistenti",
"addSelected": "Aggiungi selezionato",
"modelExists": "Il modello esiste",
"selectAndAdd": "Seleziona e aggiungi i modelli elencati",
"noModelsFound": "Nessun modello trovato",
"delete": "Elimina",
"deleteModel": "Elimina modello",
"deleteConfig": "Elimina configurazione",
"deleteMsg1": "Sei sicuro di voler eliminare questo modello da InvokeAI?",
"deleteMsg2": "Questo non eliminerà il file Checkpoint del modello dal tuo disco. Puoi aggiungerlo nuovamente se lo desideri."
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1,50 @@
{
"modelManager": "Gerente de Modelo",
"model": "Modelo",
"modelAdded": "Modelo Adicionado",
"modelUpdated": "Modelo Atualizado",
"modelEntryDeleted": "Entrada de modelo excluída",
"cannotUseSpaces": "Não pode usar espaços",
"addNew": "Adicionar Novo",
"addNewModel": "Adicionar Novo modelo",
"addManually": "Adicionar Manualmente",
"manual": "Manual",
"name": "Nome",
"nameValidationMsg": "Insira um nome para o seu modelo",
"description": "Descrição",
"descriptionValidationMsg": "Adicione uma descrição para o seu modelo",
"config": "Config",
"configValidationMsg": "Caminho para o arquivo de configuração do seu modelo.",
"modelLocation": "Localização do modelo",
"modelLocationValidationMsg": "Caminho para onde seu modelo está localizado.",
"vaeLocation": "Localização VAE",
"vaeLocationValidationMsg": "Caminho para onde seu VAE está localizado.",
"width": "Largura",
"widthValidationMsg": "Largura padrão do seu modelo.",
"height": "Altura",
"heightValidationMsg": "Altura padrão do seu modelo.",
"addModel": "Adicionar Modelo",
"updateModel": "Atualizar Modelo",
"availableModels": "Modelos Disponíveis",
"search": "Procurar",
"load": "Carregar",
"active": "Ativado",
"notLoaded": "Não carregado",
"cached": "Em cache",
"checkpointFolder": "Pasta de Checkpoint",
"clearCheckpointFolder": "Apagar Pasta de Checkpoint",
"findModels": "Encontrar Modelos",
"modelsFound": "Modelos Encontrados",
"selectFolder": "Selecione a Pasta",
"selected": "Selecionada",
"selectAll": "Selecionar Tudo",
"deselectAll": "Deselecionar Tudo",
"showExisting": "Mostrar Existente",
"addSelected": "Adicione Selecionado",
"modelExists": "Modelo Existe",
"delete": "Excluir",
"deleteModel": "Excluir modelo",
"deleteConfig": "Excluir Config",
"deleteMsg1": "Tem certeza de que deseja excluir esta entrada do modelo de InvokeAI?",
"deleteMsg2": "Isso não vai excluir o arquivo de modelo checkpoint do seu disco. Você pode lê-los, se desejar."
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1 @@
{}

View File

@@ -1 +1,62 @@
{}
{
"images": "Images",
"steps": "Steps",
"cfgScale": "CFG Scale",
"width": "Width",
"height": "Height",
"sampler": "Sampler",
"seed": "Seed",
"randomizeSeed": "Randomize Seed",
"shuffle": "Shuffle",
"noiseThreshold": "Noise Threshold",
"perlinNoise": "Perlin Noise",
"variations": "Variations",
"variationAmount": "Variation Amount",
"seedWeights": "Seed Weights",
"faceRestoration": "Face Restoration",
"restoreFaces": "Restore Faces",
"type": "Type",
"strength": "Strength",
"upscaling": "Upscaling",
"upscale": "Upscale",
"upscaleImage": "Upscale Image",
"scale": "Scale",
"otherOptions": "Other Options",
"seamlessTiling": "Seamless Tiling",
"hiresOptim": "High Res Optimization",
"imageFit": "Fit Initial Image To Output Size",
"codeformerFidelity": "Fidelity",
"seamSize": "Seam Size",
"seamBlur": "Seam Blur",
"seamStrength": "Seam Strength",
"seamSteps": "Seam Steps",
"inpaintReplace": "Inpaint Replace",
"scaleBeforeProcessing": "Scale Before Processing",
"scaledWidth": "Scaled W",
"scaledHeight": "Scaled H",
"infillMethod": "Infill Method",
"tileSize": "Tile Size",
"boundingBoxHeader": "Bounding Box",
"seamCorrectionHeader": "Seam Correction",
"infillScalingHeader": "Infill and Scaling",
"img2imgStrength": "Image To Image Strength",
"toggleLoopback": "Toggle Loopback",
"invoke": "Invoke",
"cancel": "Cancel",
"promptPlaceholder": "Type prompt here. [negative tokens], (upweight)++, (downweight)--, swap and blend are available (see docs)",
"sendTo": "Send to",
"sendToImg2Img": "Send to Image to Image",
"sendToUnifiedCanvas": "Send To Unified Canvas",
"copyImageToLink": "Copy Image To Link",
"downloadImage": "Download Image",
"openInViewer": "Open In Viewer",
"closeViewer": "Close Viewer",
"usePrompt": "Use Prompt",
"useSeed": "Use Seed",
"useAll": "Use All",
"useInitImg": "Use Initial Image",
"info": "Info",
"deleteImage": "Delete Image",
"initialImage": "Inital Image",
"showOptionsPanel": "Show Options Panel"
}

View File

@@ -43,7 +43,7 @@
"toggleLoopback": "Attiva/disattiva elaborazione ricorsiva",
"invoke": "Invoca",
"cancel": "Annulla",
"promptPlaceholder": "Digita qui il prompt. [token negativi], (aumenta il peso)++, (diminuisci il peso)--, scambia e fondi sono disponibili (consulta la documentazione)",
"promptPlaceholder": "Digita qui il prompt usando termini in lingua inglese. [token negativi], (aumenta il peso)++, (diminuisci il peso)--, scambia e fondi sono disponibili (consulta la documentazione)",
"sendTo": "Invia a",
"sendToImg2Img": "Invia a da Immagine a Immagine",
"sendToUnifiedCanvas": "Invia a Tela Unificata",

View File

@@ -0,0 +1,62 @@
{
"images": "图像",
"steps": "步数",
"cfgScale": "CFG 等级",
"width": "宽度",
"height": "高度",
"sampler": "采样算法",
"seed": "种子",
"randomizeSeed": "随机化种子",
"shuffle": "随机化",
"noiseThreshold": "噪声阈值",
"perlinNoise": "Perlin 噪声",
"variations": "变种",
"variationAmount": "变种数量",
"seedWeights": "种子权重",
"faceRestoration": "脸部修复",
"restoreFaces": "修复脸部",
"type": "种类",
"strength": "强度",
"upscaling": "放大",
"upscale": "放大",
"upscaleImage": "放大图像",
"scale": "等级",
"otherOptions": "其他选项",
"seamlessTiling": "无缝拼贴",
"hiresOptim": "高清优化",
"imageFit": "使生成图像长宽适配原图像",
"codeformerFidelity": "保真",
"seamSize": "接缝尺寸",
"seamBlur": "接缝模糊",
"seamStrength": "接缝强度",
"seamSteps": "接缝步数",
"inpaintReplace": "内画替换",
"scaleBeforeProcessing": "处理前缩放",
"scaledWidth": "缩放宽度",
"scaledHeight": "缩放长度",
"infillMethod": "填充法",
"tileSize": "方格尺寸",
"boundingBoxHeader": "选择区域",
"seamCorrectionHeader": "接缝修正",
"infillScalingHeader": "内填充和缩放",
"img2imgStrength": "图像到图像强度",
"toggleLoopback": "切换环回",
"invoke": "Invoke",
"cancel": "取消",
"promptPlaceholder": "在这里输入提示。可以使用[反提示]、(加权)++、(减权)--、交换和混合(见文档)",
"sendTo": "发送到",
"sendToImg2Img": "发送到图像到图像",
"sendToUnifiedCanvas": "发送到统一画布",
"copyImageToLink": "复制图像链接",
"downloadImage": "下载图像",
"openInViewer": "在视图中打开",
"closeViewer": "关闭视图",
"usePrompt": "使用提示",
"useSeed": "使用种子",
"useAll": "使用所有参数",
"useInitImg": "使用原图像",
"info": "信息",
"deleteImage": "删除图像",
"initialImage": "原图像",
"showOptionsPanel": "显示选项浮窗"
}

View File

@@ -1 +1,13 @@
{}
{
"models": "Models",
"displayInProgress": "Display In-Progress Images",
"saveSteps": "Save images every n steps",
"confirmOnDelete": "Confirm On Delete",
"displayHelpIcons": "Display Help Icons",
"useCanvasBeta": "Use Canvas Beta Layout",
"enableImageDebugging": "Enable Image Debugging",
"resetWebUI": "Reset Web UI",
"resetWebUIDesc1": "Resetting the web UI only resets the browser's local cache of your images and remembered settings. It does not delete any images from disk.",
"resetWebUIDesc2": "If images aren't showing up in the gallery or something else isn't working, please try resetting before submitting an issue on GitHub.",
"resetComplete": "Web UI has been reset. Refresh the page to reload."
}

View File

@@ -0,0 +1,13 @@
{
"models": "模型",
"displayInProgress": "显示进行中的图像",
"saveSteps": "每n步保存图像",
"confirmOnDelete": "删除时确认",
"displayHelpIcons": "显示帮助按钮",
"useCanvasBeta": "使用测试版画布视图",
"enableImageDebugging": "开启图像调试",
"resetWebUI": "重置网页界面",
"resetWebUIDesc1": "重置网页只会重置浏览器中缓存的图像和设置,不会删除任何图像。",
"resetWebUIDesc2": "如果图像没有显示在图库中或者其他东西不工作请在GitHub上提交问题之前尝试重置。",
"resetComplete": "网页界面已重置。刷新页面以重新加载。"
}

View File

@@ -1 +1,32 @@
{}
{
"tempFoldersEmptied": "Temp Folder Emptied",
"uploadFailed": "Upload failed",
"uploadFailedMultipleImagesDesc": "Multiple images pasted, may only upload one image at a time",
"uploadFailedUnableToLoadDesc": "Unable to load file",
"downloadImageStarted": "Image Download Started",
"imageCopied": "Image Copied",
"imageLinkCopied": "Image Link Copied",
"imageNotLoaded": "No Image Loaded",
"imageNotLoadedDesc": "No image found to send to image to image module",
"imageSavedToGallery": "Image Saved to Gallery",
"canvasMerged": "Canvas Merged",
"sentToImageToImage": "Sent To Image To Image",
"sentToUnifiedCanvas": "Sent to Unified Canvas",
"parametersSet": "Parameters Set",
"parametersNotSet": "Parameters Not Set",
"parametersNotSetDesc": "No metadata found for this image.",
"parametersFailed": "Problem loading parameters",
"parametersFailedDesc": "Unable to load init image.",
"seedSet": "Seed Set",
"seedNotSet": "Seed Not Set",
"seedNotSetDesc": "Could not find seed for this image.",
"promptSet": "Prompt Set",
"promptNotSet": "Prompt Not Set",
"promptNotSetDesc": "Could not find prompt for this image.",
"upscalingFailed": "Upscaling Failed",
"faceRestoreFailed": "Face Restoration Failed",
"metadataLoadFailed": "Failed to load metadata",
"initialImageSet": "Initial Image Set",
"initialImageNotSet": "Initial Image Not Set",
"initialImageNotSetDesc": "Could not load initial image"
}

32
frontend/dist/locales/toast/zh_cn.json vendored Normal file
View File

@@ -0,0 +1,32 @@
{
"tempFoldersEmptied": "临时文件夹已清空",
"uploadFailed": "上传失败",
"uploadFailedMultipleImagesDesc": "多张图像被粘贴,同时只能上传一张图像",
"uploadFailedUnableToLoadDesc": "无法加载文件",
"downloadImageStarted": "图像下载已开始",
"imageCopied": "图像已复制",
"imageLinkCopied": "图像链接已复制",
"imageNotLoaded": "没有加载图像",
"imageNotLoadedDesc": "没有图像可供送往图像到图像界面",
"imageSavedToGallery": "图像已保存到图库",
"canvasMerged": "画布已合并",
"sentToImageToImage": "已送往图像到图像",
"sentToUnifiedCanvas": "已送往统一画布",
"parametersSet": "参数已设定",
"parametersNotSet": "参数未设定",
"parametersNotSetDesc": "此图像不存在元数据",
"parametersFailed": "加载参数失败",
"parametersFailedDesc": "加载初始图像失败",
"seedSet": "种子已设定",
"seedNotSet": "种子未设定",
"seedNotSetDesc": "无法找到该图像的种子",
"promptSet": "提示已设定",
"promptNotSet": "提示未设定",
"promptNotSetDesc": "无法找到该图像的提示",
"upscalingFailed": "放大失败",
"faceRestoreFailed": "脸部修复失败",
"metadataLoadFailed": "加载元数据失败",
"initialImageSet": "初始图像已设定",
"initialImageNotSet": "初始图像未设定",
"initialImageNotSetDesc": "无法加载初始图像"
}

View File

@@ -1 +1,59 @@
{}
{
"layer": "Layer",
"base": "Base",
"mask": "Mask",
"maskingOptions": "Masking Options",
"enableMask": "Enable Mask",
"preserveMaskedArea": "Preserve Masked Area",
"clearMask": "Clear Mask",
"brush": "Brush",
"eraser": "Eraser",
"fillBoundingBox": "Fill Bounding Box",
"eraseBoundingBox": "Erase Bounding Box",
"colorPicker": "Color Picker",
"brushOptions": "Brush Options",
"brushSize": "Size",
"move": "Move",
"resetView": "Reset View",
"mergeVisible": "Merge Visible",
"saveToGallery": "Save To Gallery",
"copyToClipboard": "Copy to Clipboard",
"downloadAsImage": "Download As Image",
"undo": "Undo",
"redo": "Redo",
"clearCanvas": "Clear Canvas",
"canvasSettings": "Canvas Settings",
"showIntermediates": "Show Intermediates",
"showGrid": "Show Grid",
"snapToGrid": "Snap to Grid",
"darkenOutsideSelection": "Darken Outside Selection",
"autoSaveToGallery": "Auto Save to Gallery",
"saveBoxRegionOnly": "Save Box Region Only",
"limitStrokesToBox": "Limit Strokes to Box",
"showCanvasDebugInfo": "Show Canvas Debug Info",
"clearCanvasHistory": "Clear Canvas History",
"clearHistory": "Clear History",
"clearCanvasHistoryMessage": "Clearing the canvas history leaves your current canvas intact, but irreversibly clears the undo and redo history.",
"clearCanvasHistoryConfirm": "Are you sure you want to clear the canvas history?",
"emptyTempImageFolder": "Empty Temp Image Folder",
"emptyFolder": "Empty Folder",
"emptyTempImagesFolderMessage": "Emptying the temp image folder also fully resets the Unified Canvas. This includes all undo/redo history, images in the staging area, and the canvas base layer.",
"emptyTempImagesFolderConfirm": "Are you sure you want to empty the temp folder?",
"activeLayer": "Active Layer",
"canvasScale": "Canvas Scale",
"boundingBox": "Bounding Box",
"scaledBoundingBox": "Scaled Bounding Box",
"boundingBoxPosition": "Bounding Box Position",
"canvasDimensions": "Canvas Dimensions",
"canvasPosition": "Canvas Position",
"cursorPosition": "Cursor Position",
"previous": "Previous",
"next": "Next",
"accept": "Accept",
"showHide": "Show/Hide",
"discardAll": "Discard All",
"betaClear": "Clear",
"betaDarkenOutside": "Darken Outside",
"betaLimitToBox": "Limit To Box",
"betaPreserveMasked": "Preserve Masked"
}

View File

@@ -0,0 +1,59 @@
{
"layer": "图层",
"base": "基础层",
"mask": "遮罩层层",
"maskingOptions": "遮罩层选项",
"enableMask": "启用遮罩层",
"preserveMaskedArea": "保留遮罩层区域",
"clearMask": "清除遮罩层",
"brush": "刷子",
"eraser": "橡皮擦",
"fillBoundingBox": "填充选择区域",
"eraseBoundingBox": "取消选择区域",
"colorPicker": "颜色提取",
"brushOptions": "刷子选项",
"brushSize": "大小",
"move": "移动",
"resetView": "重置视图",
"mergeVisible": "合并可见层",
"saveToGallery": "保存至图库",
"copyToClipboard": "复制到剪贴板",
"downloadAsImage": "下载图像",
"undo": "撤销",
"redo": "重做",
"clearCanvas": "清除画布",
"canvasSettings": "画布设置",
"showIntermediates": "显示中间产物",
"showGrid": "显示网格",
"snapToGrid": "切换网格对齐",
"darkenOutsideSelection": "暗化外部区域",
"autoSaveToGallery": "自动保存至图库",
"saveBoxRegionOnly": "只保存框内区域",
"limitStrokesToBox": "限制画笔在框内",
"showCanvasDebugInfo": "显示画布调试信息",
"clearCanvasHistory": "清除画布历史",
"clearHistory": "清除历史",
"clearCanvasHistoryMessage": "清除画布历史不会影响当前画布,但会不可撤销地清除所有撤销/重做历史!",
"clearCanvasHistoryConfirm": "确认清除所有画布历史?",
"emptyTempImageFolder": "清除临时文件夹",
"emptyFolder": "清除文件夹",
"emptyTempImagesFolderMessage": "清空临时图像文件夹会完全重置统一画布。这包括所有的撤销/重做历史、暂存区的图像和画布基础层。",
"emptyTempImagesFolderConfirm": "确认清除临时文件夹?",
"activeLayer": "活跃图层",
"canvasScale": "画布缩放",
"boundingBox": "选择区域",
"scaledBoundingBox": "缩放选择区域",
"boundingBoxPosition": "选择区域位置",
"canvasDimensions": "画布长宽",
"canvasPosition": "画布位置",
"cursorPosition": "光标位置",
"previous": "上一张",
"next": "下一张",
"accept": "接受",
"showHide": "显示 / 隐藏",
"discardAll": "放弃所有",
"betaClear": "清除",
"betaDarkenOutside": "暗化外部区域",
"betaLimitToBox": "限制在框内",
"betaPreserveMasked": "保留遮罩层"
}

View File

@@ -27,6 +27,7 @@
"@types/uuid": "^8.3.4",
"add": "^2.0.6",
"dateformat": "^5.0.3",
"formik": "^2.2.9",
"framer-motion": "^7.2.1",
"i18next": "^22.4.5",
"i18next-browser-languagedetector": "^7.0.1",

View File

@@ -1,3 +1,56 @@
{
"hotkeysLabel": "Hotkeys"
"hotkeysLabel": "Hotkeys",
"themeLabel": "Theme",
"languagePickerLabel": "Language Picker",
"reportBugLabel": "Report Bug",
"githubLabel": "Github",
"discordLabel": "Discord",
"settingsLabel": "Settings",
"darkTheme": "Dark",
"lightTheme": "Light",
"greenTheme": "Green",
"langEnglish": "English",
"langRussian": "Russian",
"langItalian": "Italian",
"langBrPortuguese": "Portuguese (Brazilian)",
"langGerman": "German",
"langPortuguese": "Portuguese",
"langFrench": "French",
"langPolish": "Polish",
"text2img": "Text To Image",
"img2img": "Image To Image",
"unifiedCanvas": "Unified Canvas",
"nodes": "Nodes",
"nodesDesc": "A node based system for the generation of images is under development currently. Stay tuned for updates about this amazing feature.",
"postProcessing": "Post Processing",
"postProcessDesc1": "Invoke AI offers a wide variety of post processing features. Image Upscaling and Face Restoration are already available in the WebUI. You can access them from the Advanced Options menu of the Text To Image and Image To Image tabs. You can also process images directly, using the image action buttons above the current image display or in the viewer.",
"postProcessDesc2": "A dedicated UI will be released soon to facilitate more advanced post processing workflows.",
"postProcessDesc3": "The Invoke AI Command Line Interface offers various other features including Embiggen.",
"training": "Training",
"trainingDesc1": "A dedicated workflow for training your own embeddings and checkpoints using Textual Inversion and Dreambooth from the web interface.",
"trainingDesc2": "InvokeAI already supports training custom embeddings using Textual Inversion using the main script.",
"upload": "Upload",
"close": "Close",
"load": "Load",
"statusConnected": "Connected",
"statusDisconnected": "Disconnected",
"statusError": "Error",
"statusPreparing": "Preparing",
"statusProcessingCanceled": "Processing Canceled",
"statusProcessingComplete": "Processing Complete",
"statusGenerating": "Generating",
"statusGeneratingTextToImage": "Generating Text To Image",
"statusGeneratingImageToImage": "Generating Image To Image",
"statusGeneratingInpainting": "Generating Inpainting",
"statusGeneratingOutpainting": "Generating Outpainting",
"statusGenerationComplete": "Generation Complete",
"statusIterationComplete": "Iteration Complete",
"statusSavingImage": "Saving Image",
"statusRestoringFaces": "Restoring Faces",
"statusRestoringFacesGFPGAN": "Restoring Faces (GFPGAN)",
"statusRestoringFacesCodeFormer": "Restoring Faces (CodeFormer)",
"statusUpscaling": "Upscaling",
"statusUpscalingESRGAN": "Upscaling (ESRGAN)",
"statusLoadingModel": "Loading Model",
"statusModelChanged": "Model Changed"
}

View File

@@ -17,6 +17,7 @@
"langPortuguese": "Portuguese",
"langFrench": "French",
"langPolish": "Polish",
"langSimplifiedChinese": "Simplified Chinese",
"text2img": "Text To Image",
"img2img": "Image To Image",
"unifiedCanvas": "Unified Canvas",

View File

@@ -17,6 +17,7 @@
"langPortuguese": "Portoghese",
"langFrench": "Francese",
"langPolish": "Polacco",
"langSimplifiedChinese": "Cinese semplificato",
"text2img": "Testo a Immagine",
"img2img": "Immagine a Immagine",
"unifiedCanvas": "Tela unificata",

View File

@@ -0,0 +1,54 @@
{
"hotkeysLabel": "快捷键",
"themeLabel": "主题",
"languagePickerLabel": "语言",
"reportBugLabel": "提交错误报告",
"githubLabel": "GitHub",
"discordLabel": "Discord",
"settingsLabel": "设置",
"darkTheme": "暗色",
"lightTheme": "亮色",
"greenTheme": "绿色",
"langEnglish": "英语",
"langRussian": "俄语",
"langItalian": "意大利语",
"langPortuguese": "葡萄牙语",
"langFrench": "法语",
"langChineseSimplified": "简体中文",
"text2img": "文字到图像",
"img2img": "图像到图像",
"unifiedCanvas": "统一画布",
"nodes": "节点",
"nodesDesc": "一个基于节点的图像生成系统目前正在开发中。请持续关注关于这一功能的更新。",
"postProcessing": "后期处理",
"postProcessDesc1": "Invoke AI 提供各种各样的后期处理功能。图像放大和面部修复在网页界面中已经可用。你可以从文本到图像和图像到图像页面的高级选项菜单中访问它们。你也可以直接使用图像显示上方或查看器中的图像操作按钮处理图像。",
"postProcessDesc2": "一个专门的界面将很快发布,新的界面能够处理更复杂的后期处理流程。",
"postProcessDesc3": "Invoke AI 命令行界面提供例如Embiggen的各种其他功能。",
"training": "训练",
"trainingDesc1": "一个专门用于从网络UI使用Textual Inversion和Dreambooth训练自己的嵌入模型和检查点的工作流程。",
"trainingDesc2": "InvokeAI已经支持使用主脚本中的Textual Inversion来训练自定义的嵌入模型。",
"upload": "上传",
"close": "关闭",
"load": "加载",
"statusConnected": "已连接",
"statusDisconnected": "未连接",
"statusError": "错误",
"statusPreparing": "准备中",
"statusProcessingCanceled": "处理取消",
"statusProcessingComplete": "处理完成",
"statusGenerating": "生成中",
"statusGeneratingTextToImage": "文字到图像生成中",
"statusGeneratingImageToImage": "图像到图像生成中",
"statusGeneratingInpainting": "生成内画中",
"statusGeneratingOutpainting": "生成外画中",
"statusGenerationComplete": "生成完成",
"statusIterationComplete": "迭代完成",
"statusSavingImage": "图像保存中",
"statusRestoringFaces": "脸部修复中",
"statusRestoringFacesGFPGAN": "脸部修复中 (GFPGAN)",
"statusRestoringFacesCodeFormer": "脸部修复中 (CodeFormer)",
"statusUpscaling": "放大中",
"statusUpscalingESRGAN": "放大中 (ESRGAN)",
"statusLoadingModel": "模型加载中",
"statusModelChanged": "模型已切换"
}

View File

@@ -1 +1,16 @@
{}
{
"generations": "Generations",
"showGenerations": "Show Generations",
"uploads": "Uploads",
"showUploads": "Show Uploads",
"galleryImageSize": "Image Size",
"galleryImageResetSize": "Reset Size",
"gallerySettings": "Gallery Settings",
"maintainAspectRatio": "Maintain Aspect Ratio",
"autoSwitchNewImages": "Auto-Switch to New Images",
"singleColumnLayout": "Single Column Layout",
"pinGallery": "Pin Gallery",
"allImagesLoaded": "All Images Loaded",
"loadMore": "Load More",
"noImagesInGallery": "No Images In Gallery"
}

View File

@@ -0,0 +1,16 @@
{
"generations": "生成的图像",
"showGenerations": "显示生成的图像",
"uploads": "上传的图像",
"showUploads": "显示上传的图像",
"galleryImageSize": "预览大小",
"galleryImageResetSize": "重置预览大小",
"gallerySettings": "预览设置",
"maintainAspectRatio": "保持比例",
"autoSwitchNewImages": "自动切换到新图像",
"singleColumnLayout": "单列布局",
"pinGallery": "保持图库常开",
"allImagesLoaded": "所有图像加载完成",
"loadMore": "加载更多",
"noImagesInGallery": "图库中无图像"
}

View File

@@ -1 +1,207 @@
{}
{
"keyboardShortcuts": "Keyboard Shorcuts",
"appHotkeys": "App Hotkeys",
"generalHotkeys": "General Hotkeys",
"galleryHotkeys": "Gallery Hotkeys",
"unifiedCanvasHotkeys": "Unified Canvas Hotkeys",
"invoke": {
"title": "Invoke",
"desc": "Generate an image"
},
"cancel": {
"title": "Cancel",
"desc": "Cancel image generation"
},
"focusPrompt": {
"title": "Focus Prompt",
"desc": "Focus the prompt input area"
},
"toggleOptions": {
"title": "Toggle Options",
"desc": "Open and close the options panel"
},
"pinOptions": {
"title": "Pin Options",
"desc": "Pin the options panel"
},
"toggleViewer": {
"title": "Toggle Viewer",
"desc": "Open and close Image Viewer"
},
"toggleGallery": {
"title": "Toggle Gallery",
"desc": "Open and close the gallery drawer"
},
"maximizeWorkSpace": {
"title": "Maximize Workspace",
"desc": "Close panels and maximize work area"
},
"changeTabs": {
"title": "Change Tabs",
"desc": "Switch to another workspace"
},
"consoleToggle": {
"title": "Console Toggle",
"desc": "Open and close console"
},
"setPrompt": {
"title": "Set Prompt",
"desc": "Use the prompt of the current image"
},
"setSeed": {
"title": "Set Seed",
"desc": "Use the seed of the current image"
},
"setParameters": {
"title": "Set Parameters",
"desc": "Use all parameters of the current image"
},
"restoreFaces": {
"title": "Restore Faces",
"desc": "Restore the current image"
},
"upscale": {
"title": "Upscale",
"desc": "Upscale the current image"
},
"showInfo": {
"title": "Show Info",
"desc": "Show metadata info of the current image"
},
"sendToImageToImage": {
"title": "Send To Image To Image",
"desc": "Send current image to Image to Image"
},
"deleteImage": {
"title": "Delete Image",
"desc": "Delete the current image"
},
"closePanels": {
"title": "Close Panels",
"desc": "Closes open panels"
},
"previousImage": {
"title": "Previous Image",
"desc": "Display the previous image in gallery"
},
"nextImage": {
"title": "Next Image",
"desc": "Display the next image in gallery"
},
"toggleGalleryPin": {
"title": "Toggle Gallery Pin",
"desc": "Pins and unpins the gallery to the UI"
},
"increaseGalleryThumbSize": {
"title": "Increase Gallery Image Size",
"desc": "Increases gallery thumbnails size"
},
"decreaseGalleryThumbSize": {
"title": "Decrease Gallery Image Size",
"desc": "Decreases gallery thumbnails size"
},
"selectBrush": {
"title": "Select Brush",
"desc": "Selects the canvas brush"
},
"selectEraser": {
"title": "Select Eraser",
"desc": "Selects the canvas eraser"
},
"decreaseBrushSize": {
"title": "Decrease Brush Size",
"desc": "Decreases the size of the canvas brush/eraser"
},
"increaseBrushSize": {
"title": "Increase Brush Size",
"desc": "Increases the size of the canvas brush/eraser"
},
"decreaseBrushOpacity": {
"title": "Decrease Brush Opacity",
"desc": "Decreases the opacity of the canvas brush"
},
"increaseBrushOpacity": {
"title": "Increase Brush Opacity",
"desc": "Increases the opacity of the canvas brush"
},
"moveTool": {
"title": "Move Tool",
"desc": "Allows canvas navigation"
},
"fillBoundingBox": {
"title": "Fill Bounding Box",
"desc": "Fills the bounding box with brush color"
},
"eraseBoundingBox": {
"title": "Erase Bounding Box",
"desc": "Erases the bounding box area"
},
"colorPicker": {
"title": "Select Color Picker",
"desc": "Selects the canvas color picker"
},
"toggleSnap": {
"title": "Toggle Snap",
"desc": "Toggles Snap to Grid"
},
"quickToggleMove": {
"title": "Quick Toggle Move",
"desc": "Temporarily toggles Move mode"
},
"toggleLayer": {
"title": "Toggle Layer",
"desc": "Toggles mask/base layer selection"
},
"clearMask": {
"title": "Clear Mask",
"desc": "Clear the entire mask"
},
"hideMask": {
"title": "Hide Mask",
"desc": "Hide and unhide mask"
},
"showHideBoundingBox": {
"title": "Show/Hide Bounding Box",
"desc": "Toggle visibility of bounding box"
},
"mergeVisible": {
"title": "Merge Visible",
"desc": "Merge all visible layers of canvas"
},
"saveToGallery": {
"title": "Save To Gallery",
"desc": "Save current canvas to gallery"
},
"copyToClipboard": {
"title": "Copy to Clipboard",
"desc": "Copy current canvas to clipboard"
},
"downloadImage": {
"title": "Download Image",
"desc": "Download current canvas"
},
"undoStroke": {
"title": "Undo Stroke",
"desc": "Undo a brush stroke"
},
"redoStroke": {
"title": "Redo Stroke",
"desc": "Redo a brush stroke"
},
"resetView": {
"title": "Reset View",
"desc": "Reset Canvas View"
},
"previousStagingImage": {
"title": "Previous Staging Image",
"desc": "Previous Staging Area Image"
},
"nextStagingImage": {
"title": "Next Staging Image",
"desc": "Next Staging Area Image"
},
"acceptStagingImage": {
"title": "Accept Staging Image",
"desc": "Accept Current Staging Area Image"
}
}

View File

@@ -0,0 +1,207 @@
{
"keyboardShortcuts": "快捷方式",
"appHotkeys": "应用快捷方式",
"generalHotkeys": "一般快捷方式",
"galleryHotkeys": "图库快捷方式",
"unifiedCanvasHotkeys": "统一画布快捷方式",
"invoke": {
"title": "Invoke",
"desc": "生成图像"
},
"cancel": {
"title": "取消",
"desc": "取消图像生成"
},
"focusPrompt": {
"title": "打开提示框",
"desc": "打开提示文本框"
},
"toggleOptions": {
"title": "切换选项卡",
"desc": "打开或关闭选项卡"
},
"pinOptions": {
"title": "常开选项卡",
"desc": "保持选项卡常开"
},
"toggleViewer": {
"title": "切换图像视图",
"desc": "打开或关闭图像视图"
},
"toggleGallery": {
"title": "切换图库",
"desc": "打开或关闭图库"
},
"maximizeWorkSpace": {
"title": "工作台最大化",
"desc": "关闭所有浮窗,将工作区域最大化"
},
"changeTabs": {
"title": "切换卡片",
"desc": "切换到另一个工作区"
},
"consoleToggle": {
"title": "切换命令行",
"desc": "打开或关闭命令行"
},
"setPrompt": {
"title": "使用提示",
"desc": "使用当前图像的提示词"
},
"setSeed": {
"title": "使用种子",
"desc": "使用当前图像的种子"
},
"setParameters": {
"title": "使用所有参数",
"desc": "使用当前图像的所有参数"
},
"restoreFaces": {
"title": "脸部修复",
"desc": "对当前图像进行脸部修复"
},
"upscale": {
"title": "放大",
"desc": "对当前图像进行放大"
},
"showInfo": {
"title": "显示信息",
"desc": "显示当前图像的元数据"
},
"sendToImageToImage": {
"title": "送往图像到图像",
"desc": "将当前图像送往图像到图像"
},
"deleteImage": {
"title": "删除图像",
"desc": "删除当前图像"
},
"closePanels": {
"title": "关闭浮窗",
"desc": "关闭目前打开的浮窗"
},
"previousImage": {
"title": "上一张图像",
"desc": "显示相册中的上一张图像"
},
"nextImage": {
"title": "下一张图像",
"desc": "显示相册中的下一张图像"
},
"toggleGalleryPin": {
"title": "切换图库常开",
"desc": "开关图库在界面中的常开模式"
},
"increaseGalleryThumbSize": {
"title": "增大预览大小",
"desc": "增大图库中预览的大小"
},
"decreaseGalleryThumbSize": {
"title": "减小预览大小",
"desc": "减小图库中预览的大小"
},
"selectBrush": {
"title": "选择刷子",
"desc": "选择统一画布上的刷子"
},
"selectEraser": {
"title": "选择橡皮擦",
"desc": "选择统一画布上的橡皮擦"
},
"decreaseBrushSize": {
"title": "减小刷子大小",
"desc": "减小统一画布上的刷子或橡皮擦的大小"
},
"increaseBrushSize": {
"title": "增大刷子大小",
"desc": "增大统一画布上的刷子或橡皮擦的大小"
},
"decreaseBrushOpacity": {
"title": "减小刷子不透明度",
"desc": "减小统一画布上的刷子的不透明度"
},
"increaseBrushOpacity": {
"title": "增大刷子不透明度",
"desc": "增大统一画布上的刷子的不透明度"
},
"moveTool": {
"title": "移动工具",
"desc": "在画布上移动"
},
"fillBoundingBox": {
"title": "填充选择区域",
"desc": "在选择区域中填充刷子颜色"
},
"eraseBoundingBox": {
"title": "取消选择区域",
"desc": "将选择区域抹除"
},
"colorPicker": {
"title": "颜色提取工具",
"desc": "选择颜色提取工具"
},
"toggleSnap": {
"title": "切换网格对齐",
"desc": "打开或关闭网格对齐"
},
"quickToggleMove": {
"title": "快速切换移动模式",
"desc": "临时性地切换移动模式"
},
"toggleLayer": {
"title": "切换图层",
"desc": "切换遮罩/基础层的选择"
},
"clearMask": {
"title": "清除遮罩",
"desc": "清除整个遮罩层"
},
"hideMask": {
"title": "隐藏遮罩",
"desc": "隐藏或显示遮罩"
},
"showHideBoundingBox": {
"title": "显示/隐藏框选区",
"desc": "切换框选区的的显示状态"
},
"mergeVisible": {
"title": "合并可见层",
"desc": "将画板上可见层合并"
},
"saveToGallery": {
"title": "保存至图库",
"desc": "将画板当前内容保存至图库"
},
"copyToClipboard": {
"title": "复制到剪贴板",
"desc": "将画板当前内容复制到剪贴板"
},
"downloadImage": {
"title": "下载图像",
"desc": "下载画板当前内容"
},
"undoStroke": {
"title": "撤销画笔",
"desc": "撤销上一笔刷子的动作"
},
"redoStroke": {
"title": "重做画笔",
"desc": "重做上一笔刷子的动作"
},
"resetView": {
"title": "重置视图",
"desc": "重置画板视图"
},
"previousStagingImage": {
"title": "上一张暂存图像",
"desc": "上一张暂存区中的图像"
},
"nextStagingImage": {
"title": "下一张暂存图像",
"desc": "下一张暂存区中的图像"
},
"acceptStagingImage": {
"title": "接受暂存图像",
"desc": "接受当前暂存区中的图像"
}
}

View File

@@ -0,0 +1,50 @@
{
"modelManager": "Model Manager",
"model": "Model",
"modelAdded": "Model hinzugefügt",
"modelUpdated": "Model aktualisiert",
"modelEntryDeleted": "Modelleintrag gelöscht",
"cannotUseSpaces": "Leerzeichen können nicht verwendet werden",
"addNew": "Neue hinzufügen",
"addNewModel": "Neues Model hinzufügen",
"addManually": "Manuell hinzufügen",
"manual": "Manual",
"name": "Name",
"nameValidationMsg": "Geben Sie einen Namen für Ihr Model ein",
"description": "Beschreibung",
"descriptionValidationMsg": "Fügen Sie eine Beschreibung für Ihr Model hinzu",
"config": "Konfiguration",
"configValidationMsg": "Pfad zur Konfigurationsdatei Ihres Models.",
"modelLocation": "Ort des Models",
"modelLocationValidationMsg": "Pfad zum Speicherort Ihres Models.",
"vaeLocation": "VAE Ort",
"vaeLocationValidationMsg": "Pfad zum Speicherort Ihres VAE.",
"width": "Breite",
"widthValidationMsg": "Standardbreite Ihres Models.",
"height": "Höhe",
"heightValidationMsg": "Standardbhöhe Ihres Models.",
"addModel": "Model hinzufügen",
"updateModel": "Model aktualisieren",
"availableModels": "Verfügbare Models",
"search": "Suche",
"load": "Laden",
"active": "Aktiv",
"notLoaded": "nicht geladen",
"cached": "zwischengespeichert",
"checkpointFolder": "Checkpoint-Ordner",
"clearCheckpointFolder": "Checkpoint-Ordner löschen",
"findModels": "Models finden",
"modelsFound": "Models gefunden",
"selectFolder": "Ordner auswählen",
"selected": "Ausgewählt",
"selectAll": "Alles auswählen",
"deselectAll": "Alle abwählen",
"showExisting": "Vorhandene anzeigen",
"addSelected": "Auswahl hinzufügen",
"modelExists": "Model existiert",
"delete": "Löschen",
"deleteModel": "Model löschen",
"deleteConfig": "Konfiguration löschen",
"deleteMsg1": "Möchten Sie diesen Model-Eintrag wirklich aus InvokeAI löschen?",
"deleteMsg2": "Dadurch wird die Modellprüfpunktdatei nicht von Ihrer Festplatte gelöscht. Sie können sie bei Bedarf erneut hinzufügen."
}

View File

@@ -0,0 +1,50 @@
{
"modelManager": "Model Manager",
"model": "Model",
"modelAdded": "Model Added",
"modelUpdated": "Model Updated",
"modelEntryDeleted": "Model Entry Deleted",
"cannotUseSpaces": "Cannot Use Spaces",
"addNew": "Add New",
"addNewModel": "Add New Model",
"addManually": "Add Manually",
"manual": "Manual",
"name": "Name",
"nameValidationMsg": "Enter a name for your model",
"description": "Description",
"descriptionValidationMsg": "Add a description for your model",
"config": "Config",
"configValidationMsg": "Path to the config file of your model.",
"modelLocation": "Model Location",
"modelLocationValidationMsg": "Path to where your model is located.",
"vaeLocation": "VAE Location",
"vaeLocationValidationMsg": "Path to where your VAE is located.",
"width": "Width",
"widthValidationMsg": "Default width of your model.",
"height": "Height",
"heightValidationMsg": "Default height of your model.",
"addModel": "Add Model",
"updateModel": "Update Model",
"availableModels": "Available Models",
"search": "Search",
"load": "Load",
"active": "active",
"notLoaded": "not loaded",
"cached": "cached",
"checkpointFolder": "Checkpoint Folder",
"clearCheckpointFolder": "Clear Checkpoint Folder",
"findModels": "Find Models",
"modelsFound": "Models Found",
"selectFolder": "Select Folder",
"selected": "Selected",
"selectAll": "Select All",
"deselectAll": "Deselect All",
"showExisting": "Show Existing",
"addSelected": "Add Selected",
"modelExists": "Model Exists",
"delete": "Delete",
"deleteModel": "Delete Model",
"deleteConfig": "Delete Config",
"deleteMsg1": "Are you sure you want to delete this model entry from InvokeAI?",
"deleteMsg2": "This will not delete the model checkpoint file from your disk. You can readd them if you wish to."
}

View File

@@ -0,0 +1,53 @@
{
"modelManager": "Model Manager",
"model": "Model",
"modelAdded": "Model Added",
"modelUpdated": "Model Updated",
"modelEntryDeleted": "Model Entry Deleted",
"cannotUseSpaces": "Cannot Use Spaces",
"addNew": "Add New",
"addNewModel": "Add New Model",
"addManually": "Add Manually",
"manual": "Manual",
"name": "Name",
"nameValidationMsg": "Enter a name for your model",
"description": "Description",
"descriptionValidationMsg": "Add a description for your model",
"config": "Config",
"configValidationMsg": "Path to the config file of your model.",
"modelLocation": "Model Location",
"modelLocationValidationMsg": "Path to where your model is located.",
"vaeLocation": "VAE Location",
"vaeLocationValidationMsg": "Path to where your VAE is located.",
"width": "Width",
"widthValidationMsg": "Default width of your model.",
"height": "Height",
"heightValidationMsg": "Default height of your model.",
"addModel": "Add Model",
"updateModel": "Update Model",
"availableModels": "Available Models",
"search": "Search",
"load": "Load",
"active": "active",
"notLoaded": "not loaded",
"cached": "cached",
"checkpointFolder": "Checkpoint Folder",
"clearCheckpointFolder": "Clear Checkpoint Folder",
"findModels": "Find Models",
"scanAgain": "Scan Again",
"modelsFound": "Models Found",
"selectFolder": "Select Folder",
"selected": "Selected",
"selectAll": "Select All",
"deselectAll": "Deselect All",
"showExisting": "Show Existing",
"addSelected": "Add Selected",
"modelExists": "Model Exists",
"selectAndAdd": "Select and Add Models Listed Below",
"noModelsFound": "No Models Found",
"delete": "Delete",
"deleteModel": "Delete Model",
"deleteConfig": "Delete Config",
"deleteMsg1": "Are you sure you want to delete this model entry from InvokeAI?",
"deleteMsg2": "This will not delete the model checkpoint file from your disk. You can readd them if you wish to."
}

View File

@@ -0,0 +1,53 @@
{
"modelManager": "Gestione Modelli",
"model": "Modello",
"modelAdded": "Modello Aggiunto",
"modelUpdated": "Modello Aggiornato",
"modelEntryDeleted": "Modello Rimosso",
"cannotUseSpaces": "Impossibile utilizzare gli spazi",
"addNew": "Aggiungi nuovo",
"addNewModel": "Aggiungi nuovo Modello",
"addManually": "Aggiungi manualmente",
"manual": "Manuale",
"name": "Nome",
"nameValidationMsg": "Inserisci un nome per il modello",
"description": "Descrizione",
"descriptionValidationMsg": "Aggiungi una descrizione per il modello",
"config": "Config",
"configValidationMsg": "Percorso del file di configurazione del modello.",
"modelLocation": "Posizione del modello",
"modelLocationValidationMsg": "Percorso dove si trova il modello.",
"vaeLocation": "Posizione file VAE",
"vaeLocationValidationMsg": "Percorso dove si trova il file VAE.",
"width": "Larghezza",
"widthValidationMsg": "Larghezza predefinita del modello.",
"height": "Altezza",
"heightValidationMsg": "Altezza predefinita del modello.",
"addModel": "Aggiungi modello",
"updateModel": "Aggiorna modello",
"availableModels": "Modelli disponibili",
"search": "Ricerca",
"load": "Carica",
"active": "attivo",
"notLoaded": "non caricato",
"cached": "memorizzato nella cache",
"checkpointFolder": "Cartella Checkpoint",
"clearCheckpointFolder": "Svuota cartella checkpoint",
"findModels": "Trova modelli",
"scanAgain": "Scansiona nuovamente",
"modelsFound": "Modelli trovati",
"selectFolder": "Seleziona cartella",
"selected": "Selezionato",
"selectAll": "Seleziona tutto",
"deselectAll": "Deseleziona tutto",
"showExisting": "Mostra esistenti",
"addSelected": "Aggiungi selezionato",
"modelExists": "Il modello esiste",
"selectAndAdd": "Seleziona e aggiungi i modelli elencati",
"noModelsFound": "Nessun modello trovato",
"delete": "Elimina",
"deleteModel": "Elimina modello",
"deleteConfig": "Elimina configurazione",
"deleteMsg1": "Sei sicuro di voler eliminare questo modello da InvokeAI?",
"deleteMsg2": "Questo non eliminerà il file Checkpoint del modello dal tuo disco. Puoi aggiungerlo nuovamente se lo desideri."
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1,50 @@
{
"modelManager": "Gerente de Modelo",
"model": "Modelo",
"modelAdded": "Modelo Adicionado",
"modelUpdated": "Modelo Atualizado",
"modelEntryDeleted": "Entrada de modelo excluída",
"cannotUseSpaces": "Não pode usar espaços",
"addNew": "Adicionar Novo",
"addNewModel": "Adicionar Novo modelo",
"addManually": "Adicionar Manualmente",
"manual": "Manual",
"name": "Nome",
"nameValidationMsg": "Insira um nome para o seu modelo",
"description": "Descrição",
"descriptionValidationMsg": "Adicione uma descrição para o seu modelo",
"config": "Config",
"configValidationMsg": "Caminho para o arquivo de configuração do seu modelo.",
"modelLocation": "Localização do modelo",
"modelLocationValidationMsg": "Caminho para onde seu modelo está localizado.",
"vaeLocation": "Localização VAE",
"vaeLocationValidationMsg": "Caminho para onde seu VAE está localizado.",
"width": "Largura",
"widthValidationMsg": "Largura padrão do seu modelo.",
"height": "Altura",
"heightValidationMsg": "Altura padrão do seu modelo.",
"addModel": "Adicionar Modelo",
"updateModel": "Atualizar Modelo",
"availableModels": "Modelos Disponíveis",
"search": "Procurar",
"load": "Carregar",
"active": "Ativado",
"notLoaded": "Não carregado",
"cached": "Em cache",
"checkpointFolder": "Pasta de Checkpoint",
"clearCheckpointFolder": "Apagar Pasta de Checkpoint",
"findModels": "Encontrar Modelos",
"modelsFound": "Modelos Encontrados",
"selectFolder": "Selecione a Pasta",
"selected": "Selecionada",
"selectAll": "Selecionar Tudo",
"deselectAll": "Deselecionar Tudo",
"showExisting": "Mostrar Existente",
"addSelected": "Adicione Selecionado",
"modelExists": "Modelo Existe",
"delete": "Excluir",
"deleteModel": "Excluir modelo",
"deleteConfig": "Excluir Config",
"deleteMsg1": "Tem certeza de que deseja excluir esta entrada do modelo de InvokeAI?",
"deleteMsg2": "Isso não vai excluir o arquivo de modelo checkpoint do seu disco. Você pode lê-los, se desejar."
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1 @@
{}

View File

@@ -1 +1,62 @@
{}
{
"images": "Images",
"steps": "Steps",
"cfgScale": "CFG Scale",
"width": "Width",
"height": "Height",
"sampler": "Sampler",
"seed": "Seed",
"randomizeSeed": "Randomize Seed",
"shuffle": "Shuffle",
"noiseThreshold": "Noise Threshold",
"perlinNoise": "Perlin Noise",
"variations": "Variations",
"variationAmount": "Variation Amount",
"seedWeights": "Seed Weights",
"faceRestoration": "Face Restoration",
"restoreFaces": "Restore Faces",
"type": "Type",
"strength": "Strength",
"upscaling": "Upscaling",
"upscale": "Upscale",
"upscaleImage": "Upscale Image",
"scale": "Scale",
"otherOptions": "Other Options",
"seamlessTiling": "Seamless Tiling",
"hiresOptim": "High Res Optimization",
"imageFit": "Fit Initial Image To Output Size",
"codeformerFidelity": "Fidelity",
"seamSize": "Seam Size",
"seamBlur": "Seam Blur",
"seamStrength": "Seam Strength",
"seamSteps": "Seam Steps",
"inpaintReplace": "Inpaint Replace",
"scaleBeforeProcessing": "Scale Before Processing",
"scaledWidth": "Scaled W",
"scaledHeight": "Scaled H",
"infillMethod": "Infill Method",
"tileSize": "Tile Size",
"boundingBoxHeader": "Bounding Box",
"seamCorrectionHeader": "Seam Correction",
"infillScalingHeader": "Infill and Scaling",
"img2imgStrength": "Image To Image Strength",
"toggleLoopback": "Toggle Loopback",
"invoke": "Invoke",
"cancel": "Cancel",
"promptPlaceholder": "Type prompt here. [negative tokens], (upweight)++, (downweight)--, swap and blend are available (see docs)",
"sendTo": "Send to",
"sendToImg2Img": "Send to Image to Image",
"sendToUnifiedCanvas": "Send To Unified Canvas",
"copyImageToLink": "Copy Image To Link",
"downloadImage": "Download Image",
"openInViewer": "Open In Viewer",
"closeViewer": "Close Viewer",
"usePrompt": "Use Prompt",
"useSeed": "Use Seed",
"useAll": "Use All",
"useInitImg": "Use Initial Image",
"info": "Info",
"deleteImage": "Delete Image",
"initialImage": "Inital Image",
"showOptionsPanel": "Show Options Panel"
}

View File

@@ -43,7 +43,7 @@
"toggleLoopback": "Attiva/disattiva elaborazione ricorsiva",
"invoke": "Invoca",
"cancel": "Annulla",
"promptPlaceholder": "Digita qui il prompt. [token negativi], (aumenta il peso)++, (diminuisci il peso)--, scambia e fondi sono disponibili (consulta la documentazione)",
"promptPlaceholder": "Digita qui il prompt usando termini in lingua inglese. [token negativi], (aumenta il peso)++, (diminuisci il peso)--, scambia e fondi sono disponibili (consulta la documentazione)",
"sendTo": "Invia a",
"sendToImg2Img": "Invia a da Immagine a Immagine",
"sendToUnifiedCanvas": "Invia a Tela Unificata",

View File

@@ -0,0 +1,62 @@
{
"images": "图像",
"steps": "步数",
"cfgScale": "CFG 等级",
"width": "宽度",
"height": "高度",
"sampler": "采样算法",
"seed": "种子",
"randomizeSeed": "随机化种子",
"shuffle": "随机化",
"noiseThreshold": "噪声阈值",
"perlinNoise": "Perlin 噪声",
"variations": "变种",
"variationAmount": "变种数量",
"seedWeights": "种子权重",
"faceRestoration": "脸部修复",
"restoreFaces": "修复脸部",
"type": "种类",
"strength": "强度",
"upscaling": "放大",
"upscale": "放大",
"upscaleImage": "放大图像",
"scale": "等级",
"otherOptions": "其他选项",
"seamlessTiling": "无缝拼贴",
"hiresOptim": "高清优化",
"imageFit": "使生成图像长宽适配原图像",
"codeformerFidelity": "保真",
"seamSize": "接缝尺寸",
"seamBlur": "接缝模糊",
"seamStrength": "接缝强度",
"seamSteps": "接缝步数",
"inpaintReplace": "内画替换",
"scaleBeforeProcessing": "处理前缩放",
"scaledWidth": "缩放宽度",
"scaledHeight": "缩放长度",
"infillMethod": "填充法",
"tileSize": "方格尺寸",
"boundingBoxHeader": "选择区域",
"seamCorrectionHeader": "接缝修正",
"infillScalingHeader": "内填充和缩放",
"img2imgStrength": "图像到图像强度",
"toggleLoopback": "切换环回",
"invoke": "Invoke",
"cancel": "取消",
"promptPlaceholder": "在这里输入提示。可以使用[反提示]、(加权)++、(减权)--、交换和混合(见文档)",
"sendTo": "发送到",
"sendToImg2Img": "发送到图像到图像",
"sendToUnifiedCanvas": "发送到统一画布",
"copyImageToLink": "复制图像链接",
"downloadImage": "下载图像",
"openInViewer": "在视图中打开",
"closeViewer": "关闭视图",
"usePrompt": "使用提示",
"useSeed": "使用种子",
"useAll": "使用所有参数",
"useInitImg": "使用原图像",
"info": "信息",
"deleteImage": "删除图像",
"initialImage": "原图像",
"showOptionsPanel": "显示选项浮窗"
}

View File

@@ -1 +1,13 @@
{}
{
"models": "Models",
"displayInProgress": "Display In-Progress Images",
"saveSteps": "Save images every n steps",
"confirmOnDelete": "Confirm On Delete",
"displayHelpIcons": "Display Help Icons",
"useCanvasBeta": "Use Canvas Beta Layout",
"enableImageDebugging": "Enable Image Debugging",
"resetWebUI": "Reset Web UI",
"resetWebUIDesc1": "Resetting the web UI only resets the browser's local cache of your images and remembered settings. It does not delete any images from disk.",
"resetWebUIDesc2": "If images aren't showing up in the gallery or something else isn't working, please try resetting before submitting an issue on GitHub.",
"resetComplete": "Web UI has been reset. Refresh the page to reload."
}

View File

@@ -0,0 +1,13 @@
{
"models": "模型",
"displayInProgress": "显示进行中的图像",
"saveSteps": "每n步保存图像",
"confirmOnDelete": "删除时确认",
"displayHelpIcons": "显示帮助按钮",
"useCanvasBeta": "使用测试版画布视图",
"enableImageDebugging": "开启图像调试",
"resetWebUI": "重置网页界面",
"resetWebUIDesc1": "重置网页只会重置浏览器中缓存的图像和设置,不会删除任何图像。",
"resetWebUIDesc2": "如果图像没有显示在图库中或者其他东西不工作请在GitHub上提交问题之前尝试重置。",
"resetComplete": "网页界面已重置。刷新页面以重新加载。"
}

View File

@@ -1 +1,32 @@
{}
{
"tempFoldersEmptied": "Temp Folder Emptied",
"uploadFailed": "Upload failed",
"uploadFailedMultipleImagesDesc": "Multiple images pasted, may only upload one image at a time",
"uploadFailedUnableToLoadDesc": "Unable to load file",
"downloadImageStarted": "Image Download Started",
"imageCopied": "Image Copied",
"imageLinkCopied": "Image Link Copied",
"imageNotLoaded": "No Image Loaded",
"imageNotLoadedDesc": "No image found to send to image to image module",
"imageSavedToGallery": "Image Saved to Gallery",
"canvasMerged": "Canvas Merged",
"sentToImageToImage": "Sent To Image To Image",
"sentToUnifiedCanvas": "Sent to Unified Canvas",
"parametersSet": "Parameters Set",
"parametersNotSet": "Parameters Not Set",
"parametersNotSetDesc": "No metadata found for this image.",
"parametersFailed": "Problem loading parameters",
"parametersFailedDesc": "Unable to load init image.",
"seedSet": "Seed Set",
"seedNotSet": "Seed Not Set",
"seedNotSetDesc": "Could not find seed for this image.",
"promptSet": "Prompt Set",
"promptNotSet": "Prompt Not Set",
"promptNotSetDesc": "Could not find prompt for this image.",
"upscalingFailed": "Upscaling Failed",
"faceRestoreFailed": "Face Restoration Failed",
"metadataLoadFailed": "Failed to load metadata",
"initialImageSet": "Initial Image Set",
"initialImageNotSet": "Initial Image Not Set",
"initialImageNotSetDesc": "Could not load initial image"
}

View File

@@ -0,0 +1,32 @@
{
"tempFoldersEmptied": "临时文件夹已清空",
"uploadFailed": "上传失败",
"uploadFailedMultipleImagesDesc": "多张图像被粘贴,同时只能上传一张图像",
"uploadFailedUnableToLoadDesc": "无法加载文件",
"downloadImageStarted": "图像下载已开始",
"imageCopied": "图像已复制",
"imageLinkCopied": "图像链接已复制",
"imageNotLoaded": "没有加载图像",
"imageNotLoadedDesc": "没有图像可供送往图像到图像界面",
"imageSavedToGallery": "图像已保存到图库",
"canvasMerged": "画布已合并",
"sentToImageToImage": "已送往图像到图像",
"sentToUnifiedCanvas": "已送往统一画布",
"parametersSet": "参数已设定",
"parametersNotSet": "参数未设定",
"parametersNotSetDesc": "此图像不存在元数据",
"parametersFailed": "加载参数失败",
"parametersFailedDesc": "加载初始图像失败",
"seedSet": "种子已设定",
"seedNotSet": "种子未设定",
"seedNotSetDesc": "无法找到该图像的种子",
"promptSet": "提示已设定",
"promptNotSet": "提示未设定",
"promptNotSetDesc": "无法找到该图像的提示",
"upscalingFailed": "放大失败",
"faceRestoreFailed": "脸部修复失败",
"metadataLoadFailed": "加载元数据失败",
"initialImageSet": "初始图像已设定",
"initialImageNotSet": "初始图像未设定",
"initialImageNotSetDesc": "无法加载初始图像"
}

View File

@@ -1 +1,59 @@
{}
{
"layer": "Layer",
"base": "Base",
"mask": "Mask",
"maskingOptions": "Masking Options",
"enableMask": "Enable Mask",
"preserveMaskedArea": "Preserve Masked Area",
"clearMask": "Clear Mask",
"brush": "Brush",
"eraser": "Eraser",
"fillBoundingBox": "Fill Bounding Box",
"eraseBoundingBox": "Erase Bounding Box",
"colorPicker": "Color Picker",
"brushOptions": "Brush Options",
"brushSize": "Size",
"move": "Move",
"resetView": "Reset View",
"mergeVisible": "Merge Visible",
"saveToGallery": "Save To Gallery",
"copyToClipboard": "Copy to Clipboard",
"downloadAsImage": "Download As Image",
"undo": "Undo",
"redo": "Redo",
"clearCanvas": "Clear Canvas",
"canvasSettings": "Canvas Settings",
"showIntermediates": "Show Intermediates",
"showGrid": "Show Grid",
"snapToGrid": "Snap to Grid",
"darkenOutsideSelection": "Darken Outside Selection",
"autoSaveToGallery": "Auto Save to Gallery",
"saveBoxRegionOnly": "Save Box Region Only",
"limitStrokesToBox": "Limit Strokes to Box",
"showCanvasDebugInfo": "Show Canvas Debug Info",
"clearCanvasHistory": "Clear Canvas History",
"clearHistory": "Clear History",
"clearCanvasHistoryMessage": "Clearing the canvas history leaves your current canvas intact, but irreversibly clears the undo and redo history.",
"clearCanvasHistoryConfirm": "Are you sure you want to clear the canvas history?",
"emptyTempImageFolder": "Empty Temp Image Folder",
"emptyFolder": "Empty Folder",
"emptyTempImagesFolderMessage": "Emptying the temp image folder also fully resets the Unified Canvas. This includes all undo/redo history, images in the staging area, and the canvas base layer.",
"emptyTempImagesFolderConfirm": "Are you sure you want to empty the temp folder?",
"activeLayer": "Active Layer",
"canvasScale": "Canvas Scale",
"boundingBox": "Bounding Box",
"scaledBoundingBox": "Scaled Bounding Box",
"boundingBoxPosition": "Bounding Box Position",
"canvasDimensions": "Canvas Dimensions",
"canvasPosition": "Canvas Position",
"cursorPosition": "Cursor Position",
"previous": "Previous",
"next": "Next",
"accept": "Accept",
"showHide": "Show/Hide",
"discardAll": "Discard All",
"betaClear": "Clear",
"betaDarkenOutside": "Darken Outside",
"betaLimitToBox": "Limit To Box",
"betaPreserveMasked": "Preserve Masked"
}

View File

@@ -0,0 +1,59 @@
{
"layer": "图层",
"base": "基础层",
"mask": "遮罩层层",
"maskingOptions": "遮罩层选项",
"enableMask": "启用遮罩层",
"preserveMaskedArea": "保留遮罩层区域",
"clearMask": "清除遮罩层",
"brush": "刷子",
"eraser": "橡皮擦",
"fillBoundingBox": "填充选择区域",
"eraseBoundingBox": "取消选择区域",
"colorPicker": "颜色提取",
"brushOptions": "刷子选项",
"brushSize": "大小",
"move": "移动",
"resetView": "重置视图",
"mergeVisible": "合并可见层",
"saveToGallery": "保存至图库",
"copyToClipboard": "复制到剪贴板",
"downloadAsImage": "下载图像",
"undo": "撤销",
"redo": "重做",
"clearCanvas": "清除画布",
"canvasSettings": "画布设置",
"showIntermediates": "显示中间产物",
"showGrid": "显示网格",
"snapToGrid": "切换网格对齐",
"darkenOutsideSelection": "暗化外部区域",
"autoSaveToGallery": "自动保存至图库",
"saveBoxRegionOnly": "只保存框内区域",
"limitStrokesToBox": "限制画笔在框内",
"showCanvasDebugInfo": "显示画布调试信息",
"clearCanvasHistory": "清除画布历史",
"clearHistory": "清除历史",
"clearCanvasHistoryMessage": "清除画布历史不会影响当前画布,但会不可撤销地清除所有撤销/重做历史!",
"clearCanvasHistoryConfirm": "确认清除所有画布历史?",
"emptyTempImageFolder": "清除临时文件夹",
"emptyFolder": "清除文件夹",
"emptyTempImagesFolderMessage": "清空临时图像文件夹会完全重置统一画布。这包括所有的撤销/重做历史、暂存区的图像和画布基础层。",
"emptyTempImagesFolderConfirm": "确认清除临时文件夹?",
"activeLayer": "活跃图层",
"canvasScale": "画布缩放",
"boundingBox": "选择区域",
"scaledBoundingBox": "缩放选择区域",
"boundingBoxPosition": "选择区域位置",
"canvasDimensions": "画布长宽",
"canvasPosition": "画布位置",
"cursorPosition": "光标位置",
"previous": "上一张",
"next": "下一张",
"accept": "接受",
"showHide": "显示 / 隐藏",
"discardAll": "放弃所有",
"betaClear": "清除",
"betaDarkenOutside": "暗化外部区域",
"betaLimitToBox": "限制在框内",
"betaPreserveMasked": "保留遮罩层"
}

View File

@@ -164,10 +164,32 @@ export declare type ModelStatus = 'active' | 'cached' | 'not loaded';
export declare type Model = {
status: ModelStatus;
description: string;
weights: string;
config?: string;
vae?: string;
width?: number;
height?: number;
default?: boolean;
};
export declare type ModelList = Record<string, Model>;
export declare type FoundModel = {
name: string;
location: string;
};
export declare type InvokeModelConfigProps = {
name: string | undefined;
description: string | undefined;
config: string | undefined;
weights: string | undefined;
vae: string | undefined;
width: number | undefined;
height: number | undefined;
default: boolean | undefined;
};
/**
* These types type data received from the server via socketio.
*/
@@ -177,6 +199,22 @@ export declare type ModelChangeResponse = {
model_list: ModelList;
};
export declare type ModelAddedResponse = {
new_model_name: string;
model_list: ModelList;
update: boolean;
};
export declare type ModelDeletedResponse = {
deleted_model_name: string;
model_list: ModelList;
};
export declare type FoundModelResponse = {
search_folder: string;
found_models: FoundModel[];
};
export declare type SystemStatusResponse = SystemStatus;
export declare type SystemConfigResponse = SystemConfig;

View File

@@ -30,6 +30,14 @@ export const requestSystemConfig = createAction<undefined>(
'socketio/requestSystemConfig'
);
export const searchForModels = createAction<string>('socketio/searchForModels');
export const addNewModel = createAction<InvokeAI.InvokeModelConfigProps>(
'socketio/addNewModel'
);
export const deleteModel = createAction<string>('socketio/deleteModel');
export const requestModelChange = createAction<string>(
'socketio/requestModelChange'
);

View File

@@ -159,6 +159,15 @@ const makeSocketIOEmitters = (
emitRequestSystemConfig: () => {
socketio.emit('requestSystemConfig');
},
emitSearchForModels: (modelFolder: string) => {
socketio.emit('searchForModels', modelFolder);
},
emitAddNewModel: (modelConfig: InvokeAI.InvokeModelConfigProps) => {
socketio.emit('addNewModel', modelConfig);
},
emitDeleteModel: (modelName: string) => {
socketio.emit('deleteModel', modelName);
},
emitRequestModelChange: (modelName: string) => {
dispatch(modelChangeRequested());
socketio.emit('requestModelChange', modelName);

View File

@@ -17,6 +17,8 @@ import {
setModelList,
setIsCancelable,
addToast,
setFoundModels,
setSearchFolder,
} from 'features/system/store/systemSlice';
import {
@@ -351,6 +353,57 @@ const makeSocketIOListeners = (
dispatch(setInfillMethod(data.infill_methods[0]));
}
},
onFoundModels: (data: InvokeAI.FoundModelResponse) => {
const { search_folder, found_models } = data;
dispatch(setSearchFolder(search_folder));
dispatch(setFoundModels(found_models));
},
onNewModelAdded: (data: InvokeAI.ModelAddedResponse) => {
const { new_model_name, model_list, update } = data;
dispatch(setModelList(model_list));
dispatch(setIsProcessing(false));
dispatch(
addLogEntry({
timestamp: dateFormat(new Date(), 'isoDateTime'),
message: `Model Added: ${new_model_name}`,
level: 'info',
})
);
dispatch(
addToast({
title: !update
? `${i18n.t('modelmanager:modelAdded')}: ${new_model_name}`
: `${i18n.t('modelmanager:modelUpdated')}: ${new_model_name}`,
status: 'success',
duration: 2500,
isClosable: true,
})
);
},
onModelDeleted: (data: InvokeAI.ModelDeletedResponse) => {
const { deleted_model_name, model_list } = data;
dispatch(setModelList(model_list));
dispatch(setIsProcessing(false));
dispatch(
addLogEntry({
timestamp: dateFormat(new Date(), 'isoDateTime'),
message: `${i18n.t(
'modelmanager:modelAdded'
)}: ${deleted_model_name}`,
level: 'info',
})
);
dispatch(
addToast({
title: `${i18n.t(
'modelmanager:modelEntryDeleted'
)}: ${deleted_model_name}`,
status: 'success',
duration: 2500,
isClosable: true,
})
);
},
onModelChanged: (data: InvokeAI.ModelChangeResponse) => {
const { model_name, model_list } = data;
dispatch(setModelList(model_list));

View File

@@ -45,6 +45,9 @@ export const socketioMiddleware = () => {
onImageDeleted,
onSystemConfig,
onModelChanged,
onFoundModels,
onNewModelAdded,
onModelDeleted,
onModelChangeFailed,
onTempFolderEmptied,
} = makeSocketIOListeners(store);
@@ -58,6 +61,9 @@ export const socketioMiddleware = () => {
emitRequestNewImages,
emitCancelProcessing,
emitRequestSystemConfig,
emitSearchForModels,
emitAddNewModel,
emitDeleteModel,
emitRequestModelChange,
emitSaveStagingAreaImageToGallery,
emitRequestEmptyTempFolder,
@@ -107,6 +113,18 @@ export const socketioMiddleware = () => {
onSystemConfig(data);
});
socketio.on('foundModels', (data: InvokeAI.FoundModelResponse) => {
onFoundModels(data);
});
socketio.on('newModelAdded', (data: InvokeAI.ModelAddedResponse) => {
onNewModelAdded(data);
});
socketio.on('modelDeleted', (data: InvokeAI.ModelDeletedResponse) => {
onModelDeleted(data);
});
socketio.on('modelChanged', (data: InvokeAI.ModelChangeResponse) => {
onModelChanged(data);
});
@@ -166,6 +184,21 @@ export const socketioMiddleware = () => {
break;
}
case 'socketio/searchForModels': {
emitSearchForModels(action.payload);
break;
}
case 'socketio/addNewModel': {
emitAddNewModel(action.payload);
break;
}
case 'socketio/deleteModel': {
emitDeleteModel(action.payload);
break;
}
case 'socketio/requestModelChange': {
emitRequestModelChange(action.payload);
break;

View File

@@ -44,6 +44,7 @@ const systemBlacklist = [
'socketId',
'totalIterations',
'totalSteps',
'openModel',
].map((blacklistItem) => `system.${blacklistItem}`);
const galleryBlacklist = [

View File

@@ -1,7 +1,8 @@
import { Checkbox, CheckboxProps } from '@chakra-ui/react';
import type { ReactNode } from 'react';
type IAICheckboxProps = CheckboxProps & {
label: string;
label: string | ReactNode;
styleClass?: string;
};

View File

@@ -5,17 +5,19 @@ interface IAIInputProps extends InputProps {
styleClass?: string;
label?: string;
width?: string | number;
value: string;
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
value?: string;
size?: string;
onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
}
export default function IAIInput(props: IAIInputProps) {
const {
label,
label = '',
styleClass,
isDisabled = false,
fontSize = 'sm',
width,
size = 'sm',
isInvalid,
...rest
} = props;
@@ -26,18 +28,20 @@ export default function IAIInput(props: IAIInputProps) {
isInvalid={isInvalid}
isDisabled={isDisabled}
>
<FormLabel
fontSize={fontSize}
fontWeight="bold"
alignItems="center"
whiteSpace="nowrap"
marginBottom={0}
marginRight={0}
className="input-label"
>
{label}
</FormLabel>
<Input {...rest} className="input-entry" size={'sm'} width={width} />
{label !== '' && (
<FormLabel
fontSize={fontSize}
fontWeight="bold"
alignItems="center"
whiteSpace="nowrap"
marginBottom={0}
marginRight={0}
className="input-label"
>
{label}
</FormLabel>
)}
<Input {...rest} className="input-entry" size={size} width={width} />
</FormControl>
);
}

View File

@@ -24,7 +24,7 @@ interface Props extends Omit<NumberInputProps, 'onChange'> {
labelFontSize?: string | number;
width?: string | number;
showStepper?: boolean;
value: number;
value?: number;
onChange: (v: number) => void;
min: number;
max: number;

View File

@@ -56,6 +56,7 @@ export interface OptionsState {
variationAmount: number;
width: number;
shouldUseCanvasBetaLayout: boolean;
shouldShowExistingModelsInSearch: boolean;
}
const initialOptionsState: OptionsState = {
@@ -103,6 +104,7 @@ const initialOptionsState: OptionsState = {
variationAmount: 0.1,
width: 512,
shouldUseCanvasBetaLayout: false,
shouldShowExistingModelsInSearch: false,
};
const initialState: OptionsState = initialOptionsState;
@@ -404,6 +406,12 @@ export const optionsSlice = createSlice({
setShouldUseCanvasBetaLayout: (state, action: PayloadAction<boolean>) => {
state.shouldUseCanvasBetaLayout = action.payload;
},
setShouldShowExistingModelsInSearch: (
state,
action: PayloadAction<boolean>
) => {
state.shouldShowExistingModelsInSearch = action.payload;
},
},
});
@@ -460,6 +468,7 @@ export const {
setVariationAmount,
setWidth,
setShouldUseCanvasBetaLayout,
setShouldShowExistingModelsInSearch,
} = optionsSlice.actions;
export default optionsSlice.reducer;

View File

@@ -18,6 +18,7 @@ export default function LanguagePicker() {
pt_br: t('common:langBrPortuguese'),
de: t('common:langGerman'),
pl: t('common:langPolish'),
zh_cn: t('common:langSimplifiedChinese'),
};
const renderLanguagePicker = () => {

View File

@@ -0,0 +1,16 @@
.add-model-modal {
display: flex;
}
.add-model-modal-body {
display: flex;
flex-direction: column;
row-gap: 1rem;
padding-bottom: 2rem;
}
.add-model-form {
display: flex;
flex-direction: column;
row-gap: 0.5rem;
}

View File

@@ -0,0 +1,369 @@
import {
Flex,
FormControl,
FormErrorMessage,
FormHelperText,
FormLabel,
HStack,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalHeader,
ModalOverlay,
Text,
useDisclosure,
VStack,
} from '@chakra-ui/react';
import React from 'react';
import IAIInput from 'common/components/IAIInput';
import IAINumberInput from 'common/components/IAINumberInput';
import IAICheckbox from 'common/components/IAICheckbox';
import IAIButton from 'common/components/IAIButton';
import SearchModels from './SearchModels';
import { addNewModel } from 'app/socketio/actions';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import { FaPlus } from 'react-icons/fa';
import { Field, Formik } from 'formik';
import { useTranslation } from 'react-i18next';
import type { FieldInputProps, FormikProps } from 'formik';
import type { RootState } from 'app/store';
import type { InvokeModelConfigProps } from 'app/invokeai';
const MIN_MODEL_SIZE = 64;
const MAX_MODEL_SIZE = 2048;
export default function AddModel() {
const { isOpen, onOpen, onClose } = useDisclosure();
const dispatch = useAppDispatch();
const { t } = useTranslation();
const isProcessing = useAppSelector(
(state: RootState) => state.system.isProcessing
);
function hasWhiteSpace(s: string) {
return /\\s/g.test(s);
}
function baseValidation(value: string) {
let error;
if (hasWhiteSpace(value)) error = t('modelmanager:cannotUseSpaces');
return error;
}
const addModelFormValues: InvokeModelConfigProps = {
name: '',
description: '',
config: 'configs/stable-diffusion/v1-inference.yaml',
weights: '',
vae: '',
width: 512,
height: 512,
default: false,
};
const addModelFormSubmitHandler = (values: InvokeModelConfigProps) => {
dispatch(addNewModel(values));
onClose();
};
const addModelModalClose = () => {
onClose();
};
const [addManually, setAddmanually] = React.useState<boolean>(false);
return (
<>
<IAIButton
aria-label={t('modelmanager:addNewModel')}
tooltip={t('modelmanager:addNewModel')}
onClick={onOpen}
className="modal-close-btn"
size={'sm'}
>
<Flex columnGap={'0.5rem'} alignItems="center">
<FaPlus />
{t('modelmanager:addNew')}
</Flex>
</IAIButton>
<Modal
isOpen={isOpen}
onClose={addModelModalClose}
size="3xl"
closeOnOverlayClick={false}
>
<ModalOverlay />
<ModalContent className="modal add-model-modal">
<ModalHeader>{t('modelmanager:addNewModel')}</ModalHeader>
<ModalCloseButton />
<ModalBody className="add-model-modal-body">
<SearchModels />
<IAICheckbox
label={t('modelmanager:addManually')}
isChecked={addManually}
onChange={() => setAddmanually(!addManually)}
/>
{addManually && (
<Formik
initialValues={addModelFormValues}
onSubmit={addModelFormSubmitHandler}
>
{({ handleSubmit, errors, touched }) => (
<form onSubmit={handleSubmit}>
<VStack rowGap={'0.5rem'}>
<Text fontSize={20} fontWeight="bold" alignSelf={'start'}>
{t('modelmanager:manual')}
</Text>
{/* Name */}
<FormControl
isInvalid={!!errors.name && touched.name}
isRequired
>
<FormLabel htmlFor="name" fontSize="sm">
{t('modelmanager:name')}
</FormLabel>
<VStack alignItems={'start'}>
<Field
as={IAIInput}
id="name"
name="name"
type="text"
validate={baseValidation}
width="2xl"
/>
{!!errors.name && touched.name ? (
<FormErrorMessage>{errors.name}</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelmanager:nameValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
{/* Description */}
<FormControl
isInvalid={!!errors.description && touched.description}
isRequired
>
<FormLabel htmlFor="description" fontSize="sm">
{t('modelmanager:description')}
</FormLabel>
<VStack alignItems={'start'}>
<Field
as={IAIInput}
id="description"
name="description"
type="text"
width="2xl"
/>
{!!errors.description && touched.description ? (
<FormErrorMessage>
{errors.description}
</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelmanager:descriptionValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
{/* Config */}
<FormControl
isInvalid={!!errors.config && touched.config}
isRequired
>
<FormLabel htmlFor="config" fontSize="sm">
{t('modelmanager:config')}
</FormLabel>
<VStack alignItems={'start'}>
<Field
as={IAIInput}
id="config"
name="config"
type="text"
width="2xl"
/>
{!!errors.config && touched.config ? (
<FormErrorMessage>{errors.config}</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelmanager:configValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
{/* Weights */}
<FormControl
isInvalid={!!errors.weights && touched.weights}
isRequired
>
<FormLabel htmlFor="config" fontSize="sm">
{t('modelmanager:modelLocation')}
</FormLabel>
<VStack alignItems={'start'}>
<Field
as={IAIInput}
id="weights"
name="weights"
type="text"
width="2xl"
/>
{!!errors.weights && touched.weights ? (
<FormErrorMessage>
{errors.weights}
</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelmanager:modelLocationValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
{/* VAE */}
<FormControl isInvalid={!!errors.vae && touched.vae}>
<FormLabel htmlFor="vae" fontSize="sm">
{t('modelmanager:vaeLocation')}
</FormLabel>
<VStack alignItems={'start'}>
<Field
as={IAIInput}
id="vae"
name="vae"
type="text"
width="2xl"
/>
{!!errors.vae && touched.vae ? (
<FormErrorMessage>{errors.vae}</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelmanager:vaeLocationValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
<HStack width={'100%'}>
{/* Width */}
<FormControl
isInvalid={!!errors.width && touched.width}
>
<FormLabel htmlFor="width" fontSize="sm">
{t('modelmanager:width')}
</FormLabel>
<VStack alignItems={'start'}>
<Field id="width" name="width">
{({
field,
form,
}: {
field: FieldInputProps<number>;
form: FormikProps<InvokeModelConfigProps>;
}) => (
<IAINumberInput
id="width"
name="width"
min={MIN_MODEL_SIZE}
max={MAX_MODEL_SIZE}
step={64}
width="90%"
value={form.values.width}
onChange={(value) =>
form.setFieldValue(
field.name,
Number(value)
)
}
/>
)}
</Field>
{!!errors.width && touched.width ? (
<FormErrorMessage>
{errors.width}
</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelmanager:widthValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
{/* Height */}
<FormControl
isInvalid={!!errors.height && touched.height}
>
<FormLabel htmlFor="height" fontSize="sm">
{t('modelmanager:height')}
</FormLabel>
<VStack alignItems={'start'}>
<Field id="height" name="height">
{({
field,
form,
}: {
field: FieldInputProps<number>;
form: FormikProps<InvokeModelConfigProps>;
}) => (
<IAINumberInput
id="height"
name="height"
min={MIN_MODEL_SIZE}
max={MAX_MODEL_SIZE}
width="90%"
step={64}
value={form.values.height}
onChange={(value) =>
form.setFieldValue(
field.name,
Number(value)
)
}
/>
)}
</Field>
{!!errors.height && touched.height ? (
<FormErrorMessage>
{errors.height}
</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelmanager:heightValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
</HStack>
<IAIButton
type="submit"
className="modal-close-btn"
isLoading={isProcessing}
>
{t('modelmanager:addModel')}
</IAIButton>
</VStack>
</form>
)}
</Formik>
)}
</ModalBody>
</ModalContent>
</Modal>
</>
);
}

View File

@@ -0,0 +1,322 @@
import { createSelector } from '@reduxjs/toolkit';
import React, { useEffect, useState } from 'react';
import IAIInput from 'common/components/IAIInput';
import IAINumberInput from 'common/components/IAINumberInput';
import IAIButton from 'common/components/IAIButton';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import { systemSelector } from 'features/system/store/systemSelectors';
import {
Flex,
FormControl,
FormErrorMessage,
FormHelperText,
FormLabel,
HStack,
Text,
VStack,
} from '@chakra-ui/react';
import { Field, Formik } from 'formik';
import { useTranslation } from 'react-i18next';
import { addNewModel } from 'app/socketio/actions';
import _ from 'lodash';
import type { RootState } from 'app/store';
import type { FieldInputProps, FormikProps } from 'formik';
import type { InvokeModelConfigProps } from 'app/invokeai';
const selector = createSelector(
[systemSelector],
(system) => {
const { openModel, model_list } = system;
return {
model_list,
openModel,
};
},
{
memoizeOptions: {
resultEqualityCheck: _.isEqual,
},
}
);
const MIN_MODEL_SIZE = 64;
const MAX_MODEL_SIZE = 2048;
export default function ModelEdit() {
const { openModel, model_list } = useAppSelector(selector);
const isProcessing = useAppSelector(
(state: RootState) => state.system.isProcessing
);
const dispatch = useAppDispatch();
const { t } = useTranslation();
const [editModelFormValues, setEditModelFormValues] =
useState<InvokeModelConfigProps>({
name: '',
description: '',
config: 'configs/stable-diffusion/v1-inference.yaml',
weights: '',
vae: '',
width: 512,
height: 512,
default: false,
});
useEffect(() => {
if (openModel) {
const retrievedModel = _.pickBy(model_list, (val, key) => {
return _.isEqual(key, openModel);
});
setEditModelFormValues({
name: openModel,
description: retrievedModel[openModel]?.description,
config: retrievedModel[openModel]?.config,
weights: retrievedModel[openModel]?.weights,
vae: retrievedModel[openModel]?.vae,
width: retrievedModel[openModel]?.width,
height: retrievedModel[openModel]?.height,
default: retrievedModel[openModel]?.default,
});
}
}, [model_list, openModel]);
const editModelFormSubmitHandler = (values: InvokeModelConfigProps) => {
dispatch(addNewModel(values));
};
return openModel ? (
<Flex flexDirection="column" rowGap="1rem" width="100%">
<Flex alignItems="center">
<Text fontSize="lg" fontWeight="bold">
{openModel}
</Text>
</Flex>
<Flex
flexDirection="column"
maxHeight={window.innerHeight - 270}
overflowY="scroll"
paddingRight="2rem"
>
<Formik
enableReinitialize={true}
initialValues={editModelFormValues}
onSubmit={editModelFormSubmitHandler}
>
{({ handleSubmit, errors, touched }) => (
<form onSubmit={handleSubmit}>
<VStack rowGap={'0.5rem'} alignItems="start">
{/* Description */}
<FormControl
isInvalid={!!errors.description && touched.description}
isRequired
>
<FormLabel htmlFor="description" fontSize="sm">
{t('modelmanager:description')}
</FormLabel>
<VStack alignItems={'start'}>
<Field
as={IAIInput}
id="description"
name="description"
type="text"
width="lg"
/>
{!!errors.description && touched.description ? (
<FormErrorMessage>{errors.description}</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelmanager:descriptionValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
{/* Config */}
<FormControl
isInvalid={!!errors.config && touched.config}
isRequired
>
<FormLabel htmlFor="config" fontSize="sm">
{t('modelmanager:config')}
</FormLabel>
<VStack alignItems={'start'}>
<Field
as={IAIInput}
id="config"
name="config"
type="text"
width="lg"
/>
{!!errors.config && touched.config ? (
<FormErrorMessage>{errors.config}</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelmanager:configValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
{/* Weights */}
<FormControl
isInvalid={!!errors.weights && touched.weights}
isRequired
>
<FormLabel htmlFor="config" fontSize="sm">
{t('modelmanager:modelLocation')}
</FormLabel>
<VStack alignItems={'start'}>
<Field
as={IAIInput}
id="weights"
name="weights"
type="text"
width="lg"
/>
{!!errors.weights && touched.weights ? (
<FormErrorMessage>{errors.weights}</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelmanager:modelLocationValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
{/* VAE */}
<FormControl isInvalid={!!errors.vae && touched.vae}>
<FormLabel htmlFor="vae" fontSize="sm">
{t('modelmanager:vaeLocation')}
</FormLabel>
<VStack alignItems={'start'}>
<Field
as={IAIInput}
id="vae"
name="vae"
type="text"
width="lg"
/>
{!!errors.vae && touched.vae ? (
<FormErrorMessage>{errors.vae}</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelmanager:vaeLocationValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
<HStack width={'100%'}>
{/* Width */}
<FormControl isInvalid={!!errors.width && touched.width}>
<FormLabel htmlFor="width" fontSize="sm">
{t('modelmanager:width')}
</FormLabel>
<VStack alignItems={'start'}>
<Field id="width" name="width">
{({
field,
form,
}: {
field: FieldInputProps<number>;
form: FormikProps<InvokeModelConfigProps>;
}) => (
<IAINumberInput
id="width"
name="width"
min={MIN_MODEL_SIZE}
max={MAX_MODEL_SIZE}
step={64}
value={form.values.width}
onChange={(value) =>
form.setFieldValue(field.name, Number(value))
}
/>
)}
</Field>
{!!errors.width && touched.width ? (
<FormErrorMessage>{errors.width}</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelmanager:widthValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
{/* Height */}
<FormControl isInvalid={!!errors.height && touched.height}>
<FormLabel htmlFor="height" fontSize="sm">
{t('modelmanager:height')}
</FormLabel>
<VStack alignItems={'start'}>
<Field id="height" name="height">
{({
field,
form,
}: {
field: FieldInputProps<number>;
form: FormikProps<InvokeModelConfigProps>;
}) => (
<IAINumberInput
id="height"
name="height"
min={MIN_MODEL_SIZE}
max={MAX_MODEL_SIZE}
step={64}
value={form.values.height}
onChange={(value) =>
form.setFieldValue(field.name, Number(value))
}
/>
)}
</Field>
{!!errors.height && touched.height ? (
<FormErrorMessage>{errors.height}</FormErrorMessage>
) : (
<FormHelperText margin={0}>
{t('modelmanager:heightValidationMsg')}
</FormHelperText>
)}
</VStack>
</FormControl>
</HStack>
<IAIButton
type="submit"
className="modal-close-btn"
isLoading={isProcessing}
>
{t('modelmanager:updateModel')}
</IAIButton>
</VStack>
</form>
)}
</Formik>
</Flex>
</Flex>
) : (
<Flex
width="100%"
height="250px"
justifyContent="center"
alignItems="center"
backgroundColor="var(--background-color)"
borderRadius="0.5rem"
>
<Text fontWeight="bold" color="var(--subtext-color-bright)">
Pick A Model To Edit
</Text>
</Flex>
);
}

View File

@@ -0,0 +1,102 @@
import { useState } from 'react';
import { Flex, Text } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import IAIInput from 'common/components/IAIInput';
import AddModel from './AddModel';
import ModelListItem from './ModelListItem';
import { useAppSelector } from 'app/storeHooks';
import { useTranslation } from 'react-i18next';
import _ from 'lodash';
import type { ChangeEvent, ReactNode } from 'react';
import type { RootState } from 'app/store';
import type { SystemState } from 'features/system/store/systemSlice';
const modelListSelector = createSelector(
(state: RootState) => state.system,
(system: SystemState) => {
const models = _.map(system.model_list, (model, key) => {
return { name: key, ...model };
});
const activeModel = models.find((model) => model.status === 'active');
return {
models,
activeModel: activeModel,
};
}
);
const ModelList = () => {
const { models } = useAppSelector(modelListSelector);
const [searchText, setSearchText] = useState<string>('');
const { t } = useTranslation();
const handleSearchFilter = _.debounce((e: ChangeEvent<HTMLInputElement>) => {
setSearchText(e.target.value);
}, 400);
const renderModelListItems = () => {
const modelListItemsToRender: ReactNode[] = [];
const filteredModelListItemsToRender: ReactNode[] = [];
models.forEach((model, i) => {
if (model.name.startsWith(searchText)) {
filteredModelListItemsToRender.push(
<ModelListItem
key={i}
name={model.name}
status={model.status}
description={model.description}
/>
);
}
modelListItemsToRender.push(
<ModelListItem
key={i}
name={model.name}
status={model.status}
description={model.description}
/>
);
});
return searchText !== ''
? filteredModelListItemsToRender
: modelListItemsToRender;
};
return (
<Flex flexDirection={'column'} rowGap="2rem" width="50%" minWidth="50%">
<Flex justifyContent={'space-between'}>
<Text fontSize={'1.4rem'} fontWeight="bold">
{t('modelmanager:availableModels')}
</Text>
<AddModel />
</Flex>
<IAIInput
onChange={handleSearchFilter}
label={t('modelmanager:search')}
/>
<Flex
flexDirection={'column'}
gap={1}
maxHeight={window.innerHeight - 360}
overflow={'scroll'}
paddingRight="1rem"
>
{renderModelListItems()}
</Flex>
</Flex>
);
};
export default ModelList;

View File

@@ -0,0 +1,120 @@
import { EditIcon, DeleteIcon } from '@chakra-ui/icons';
import { Box, Button, Flex, Spacer, Text, Tooltip } from '@chakra-ui/react';
import { ModelStatus } from 'app/invokeai';
import { deleteModel, requestModelChange } from 'app/socketio/actions';
import { RootState } from 'app/store';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import IAIAlertDialog from 'common/components/IAIAlertDialog';
import IAIIconButton from 'common/components/IAIIconButton';
import { setOpenModel } from 'features/system/store/systemSlice';
import React from 'react';
import { useTranslation } from 'react-i18next';
type ModelListItemProps = {
name: string;
status: ModelStatus;
description: string;
};
export default function ModelListItem(props: ModelListItemProps) {
const { isProcessing, isConnected } = useAppSelector(
(state: RootState) => state.system
);
const openModel = useAppSelector(
(state: RootState) => state.system.openModel
);
const { t } = useTranslation();
const dispatch = useAppDispatch();
const { name, status, description } = props;
const handleChangeModel = () => {
dispatch(requestModelChange(name));
};
const openModelHandler = () => {
dispatch(setOpenModel(name));
};
const handleModelDelete = () => {
dispatch(deleteModel(name));
dispatch(setOpenModel(null));
};
const statusTextColor = () => {
switch (status) {
case 'active':
return 'var(--status-good-color)';
case 'cached':
return 'var(--status-working-color)';
case 'not loaded':
return 'var(--text-color-secondary)';
}
};
return (
<Flex
alignItems={'center'}
padding="0.5rem 0.5rem"
borderRadius="0.2rem"
backgroundColor={name === openModel ? 'var(--accent-color)' : ''}
_hover={{
backgroundColor:
name === openModel
? 'var(--accent-color)'
: 'var(--background-color)',
}}
>
<Box onClick={openModelHandler} cursor="pointer">
<Tooltip label={description} hasArrow placement="bottom">
<Text fontWeight={'bold'}>{name}</Text>
</Tooltip>
</Box>
<Spacer onClick={openModelHandler} cursor="pointer" />
<Flex gap={2} alignItems="center">
<Text color={statusTextColor()}>{status}</Text>
<Button
size={'sm'}
onClick={handleChangeModel}
isDisabled={status === 'active' || isProcessing || !isConnected}
className="modal-close-btn"
>
{t('modelmanager:load')}
</Button>
<IAIIconButton
icon={<EditIcon />}
size={'sm'}
onClick={openModelHandler}
aria-label="Modify Config"
isDisabled={status === 'active' || isProcessing || !isConnected}
className=" modal-close-btn"
/>
<IAIAlertDialog
title={t('modelmanager:deleteModel')}
acceptCallback={handleModelDelete}
acceptButtonText={t('modelmanager:delete')}
triggerComponent={
<IAIIconButton
icon={<DeleteIcon />}
size={'sm'}
aria-label={t('modelmanager:deleteConfig')}
isDisabled={status === 'active' || isProcessing || !isConnected}
className=" modal-close-btn"
style={{ backgroundColor: 'var(--btn-delete-image)' }}
/>
}
>
<Flex rowGap={'1rem'} flexDirection="column">
<p style={{ fontWeight: 'bold' }}>{t('modelmanager:deleteMsg1')}</p>
<p style={{ color: 'var(--text-color-secondary' }}>
{t('modelmanager:deleteMsg2')}
</p>
</Flex>
</IAIAlertDialog>
</Flex>
</Flex>
);
}

View File

@@ -0,0 +1,59 @@
import {
Flex,
Modal,
ModalCloseButton,
ModalContent,
ModalHeader,
ModalOverlay,
useDisclosure,
} from '@chakra-ui/react';
import React, { cloneElement } from 'react';
import { useTranslation } from 'react-i18next';
import ModelEdit from './ModelEdit';
import ModelList from './ModelList';
import type { ReactElement } from 'react';
type ModelManagerModalProps = {
children: ReactElement;
};
export default function ModelManagerModal({
children,
}: ModelManagerModalProps) {
const {
isOpen: isModelManagerModalOpen,
onOpen: onModelManagerModalOpen,
onClose: onModelManagerModalClose,
} = useDisclosure();
const { t } = useTranslation();
return (
<>
{cloneElement(children, {
onClick: onModelManagerModalOpen,
})}
<Modal
isOpen={isModelManagerModalOpen}
onClose={onModelManagerModalClose}
size="6xl"
>
<ModalOverlay />
<ModalContent className=" modal">
<ModalCloseButton className="modal-close-btn" />
<ModalHeader>{t('modelmanager:modelManager')}</ModalHeader>
<Flex
padding={'0 1.5rem 1.5rem 1.5rem'}
width="100%"
columnGap={'2rem'}
>
<ModelList />
<ModelEdit />
</Flex>
</ModalContent>
</Modal>
</>
);
}

View File

@@ -0,0 +1,394 @@
import React from 'react';
import IAICheckbox from 'common/components/IAICheckbox';
import IAIButton from 'common/components/IAIButton';
import IAIIconButton from 'common/components/IAIIconButton';
import { createSelector } from '@reduxjs/toolkit';
import { systemSelector } from 'features/system/store/systemSelectors';
import { Box, Flex, FormControl, HStack, Text, VStack } from '@chakra-ui/react';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import { useTranslation } from 'react-i18next';
import { FaPlus } from 'react-icons/fa';
import { MdFindInPage } from 'react-icons/md';
import { addNewModel, searchForModels } from 'app/socketio/actions';
import {
setFoundModels,
setSearchFolder,
} from 'features/system/store/systemSlice';
import { setShouldShowExistingModelsInSearch } from 'features/options/store/optionsSlice';
import _ from 'lodash';
import type { RootState } from 'app/store';
import type { ReactNode, ChangeEvent } from 'react';
import type { FoundModel } from 'app/invokeai';
import IAIInput from 'common/components/IAIInput';
import { Field, Formik } from 'formik';
import { BiReset } from 'react-icons/bi';
const existingModelsSelector = createSelector([systemSelector], (system) => {
const { model_list } = system;
const existingModels: string[] = [];
_.forEach(model_list, (value) => {
existingModels.push(value.weights);
});
return existingModels;
});
function ModelExistsTag() {
const { t } = useTranslation();
return (
<Box
position={'absolute'}
zIndex={2}
right={4}
top={4}
fontSize="0.7rem"
fontWeight={'bold'}
backgroundColor={'var(--accent-color)'}
padding={'0.2rem 0.5rem'}
borderRadius="0.2rem"
alignItems={'center'}
>
{t('modelmanager:modelExists')}
</Box>
);
}
interface SearchModelEntry {
model: FoundModel;
modelsToAdd: string[];
setModelsToAdd: React.Dispatch<React.SetStateAction<string[]>>;
}
function SearchModelEntry({
model,
modelsToAdd,
setModelsToAdd,
}: SearchModelEntry) {
const existingModels = useAppSelector(existingModelsSelector);
const foundModelsChangeHandler = (e: ChangeEvent<HTMLInputElement>) => {
if (!modelsToAdd.includes(e.target.value)) {
setModelsToAdd([...modelsToAdd, e.target.value]);
} else {
setModelsToAdd(_.remove(modelsToAdd, (v) => v !== e.target.value));
}
};
return (
<Box position="relative">
{existingModels.includes(model.location) ? <ModelExistsTag /> : null}
<IAICheckbox
value={model.name}
label={
<>
<VStack alignItems={'start'}>
<p style={{ fontWeight: 'bold' }}>{model.name}</p>
<p style={{ fontStyle: 'italic' }}>{model.location}</p>
</VStack>
</>
}
isChecked={modelsToAdd.includes(model.name)}
isDisabled={existingModels.includes(model.location)}
onChange={foundModelsChangeHandler}
padding={'1rem'}
backgroundColor={'var(--background-color)'}
borderRadius={'0.5rem'}
_checked={{
backgroundColor: 'var(--accent-color)',
color: 'var(--text-color)',
}}
_disabled={{
backgroundColor: 'var(--background-color-secondary)',
}}
></IAICheckbox>
</Box>
);
}
export default function SearchModels() {
const dispatch = useAppDispatch();
const { t } = useTranslation();
const searchFolder = useAppSelector(
(state: RootState) => state.system.searchFolder
);
const foundModels = useAppSelector(
(state: RootState) => state.system.foundModels
);
const existingModels = useAppSelector(existingModelsSelector);
const shouldShowExistingModelsInSearch = useAppSelector(
(state: RootState) => state.options.shouldShowExistingModelsInSearch
);
const isProcessing = useAppSelector(
(state: RootState) => state.system.isProcessing
);
const [modelsToAdd, setModelsToAdd] = React.useState<string[]>([]);
const resetSearchModelHandler = () => {
dispatch(setSearchFolder(null));
dispatch(setFoundModels(null));
setModelsToAdd([]);
};
const findModelsHandler = (values: { checkpointFolder: string }) => {
dispatch(searchForModels(values.checkpointFolder));
};
const addAllToSelected = () => {
setModelsToAdd([]);
if (foundModels) {
foundModels.forEach((model) => {
if (!existingModels.includes(model.location)) {
setModelsToAdd((currentModels) => {
return [...currentModels, model.name];
});
}
});
}
};
const removeAllFromSelected = () => {
setModelsToAdd([]);
};
const addSelectedModels = () => {
const modelsToBeAdded = foundModels?.filter((foundModel) =>
modelsToAdd.includes(foundModel.name)
);
modelsToBeAdded?.forEach((model) => {
const modelFormat = {
name: model.name,
description: '',
config: 'configs/stable-diffusion/v1-inference.yaml',
weights: model.location,
vae: '',
width: 512,
height: 512,
default: false,
};
dispatch(addNewModel(modelFormat));
});
setModelsToAdd([]);
};
const renderFoundModels = () => {
const newFoundModels: ReactNode[] = [];
const existingFoundModels: ReactNode[] = [];
if (foundModels) {
foundModels.forEach((model, index) => {
if (existingModels.includes(model.location)) {
existingFoundModels.push(
<SearchModelEntry
key={index}
model={model}
modelsToAdd={modelsToAdd}
setModelsToAdd={setModelsToAdd}
/>
);
} else {
newFoundModels.push(
<SearchModelEntry
key={index}
model={model}
modelsToAdd={modelsToAdd}
setModelsToAdd={setModelsToAdd}
/>
);
}
});
}
return (
<>
{newFoundModels}
{shouldShowExistingModelsInSearch && existingFoundModels}
</>
);
};
return (
<>
{searchFolder ? (
<Flex
flexDirection={'column'}
padding={'1rem'}
backgroundColor={'var(--background-color)'}
borderRadius="0.5rem"
rowGap={'0.5rem'}
position={'relative'}
>
<p
style={{
fontWeight: 'bold',
fontSize: '0.8rem',
backgroundColor: 'var(--background-color-secondary)',
padding: '0.2rem 1rem',
width: 'max-content',
borderRadius: '0.2rem',
}}
>
{t('modelmanager:checkpointFolder')}
</p>
<p
style={{ fontWeight: 'bold', fontSize: '0.8rem', maxWidth: '80%' }}
>
{searchFolder}
</p>
<IAIIconButton
aria-label={t('modelmanager:scanAgain')}
tooltip={t('modelmanager:scanAgain')}
icon={<BiReset />}
position={'absolute'}
right={16}
fontSize={18}
disabled={isProcessing}
onClick={() => dispatch(searchForModels(searchFolder))}
/>
<IAIIconButton
aria-label={t('modelmanager:clearCheckpointFolder')}
icon={<FaPlus style={{ transform: 'rotate(45deg)' }} />}
position={'absolute'}
right={5}
onClick={resetSearchModelHandler}
/>
</Flex>
) : (
<Formik
initialValues={{ checkpointFolder: '' }}
onSubmit={(values) => {
findModelsHandler(values);
}}
>
{({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
<HStack columnGap="0.5rem">
<FormControl isRequired width="max-content">
<Field
as={IAIInput}
id="checkpointFolder"
name="checkpointFolder"
type="text"
width="lg"
size="md"
label={t('modelmanager:checkpointFolder')}
/>
</FormControl>
<IAIIconButton
icon={<MdFindInPage />}
aria-label={t('modelmanager:findModels')}
tooltip={t('modelmanager:findModels')}
type="submit"
disabled={isProcessing}
/>
</HStack>
</form>
)}
</Formik>
)}
{foundModels && (
<Flex flexDirection={'column'} rowGap={'1rem'}>
<Flex justifyContent={'space-between'} alignItems="center">
<p>
{t('modelmanager:modelsFound')}: {foundModels.length}
</p>
<p>
{t('modelmanager:selected')}: {modelsToAdd.length}
</p>
</Flex>
<Flex columnGap={'0.5rem'} justifyContent={'space-between'}>
<Flex columnGap={'0.5rem'}>
<IAIButton
isDisabled={modelsToAdd.length === foundModels.length}
onClick={addAllToSelected}
>
{t('modelmanager:selectAll')}
</IAIButton>
<IAIButton
isDisabled={modelsToAdd.length === 0}
onClick={removeAllFromSelected}
>
{t('modelmanager:deselectAll')}
</IAIButton>
<IAICheckbox
label={t('modelmanager:showExisting')}
isChecked={shouldShowExistingModelsInSearch}
onChange={() =>
dispatch(
setShouldShowExistingModelsInSearch(
!shouldShowExistingModelsInSearch
)
)
}
/>
</Flex>
<IAIButton
isDisabled={modelsToAdd.length === 0}
onClick={addSelectedModels}
backgroundColor={
modelsToAdd.length > 0 ? 'var(--accent-color) !important' : ''
}
>
{t('modelmanager:addSelected')}
</IAIButton>
</Flex>
<Flex
rowGap="1rem"
flexDirection="column"
maxHeight="18rem"
overflowY="scroll"
paddingRight="1rem"
paddingLeft="0.2rem"
borderRadius="0.2rem"
>
{foundModels.length > 0 ? (
modelsToAdd.length === 0 && (
<Text
fontWeight="bold"
fontSize={14}
padding="0.5rem"
borderRadius="0.2rem"
margin="0 0.5rem 0 1rem"
textAlign="center"
backgroundColor="var(--notice-color)"
boxShadow="0 0 200px 6px var(--notice-color)"
marginTop="1rem"
width="max-content"
>
{t('modelmanager:selectAndAdd')}
</Text>
)
) : (
<Text
fontWeight="bold"
fontSize={14}
padding="0.5rem"
borderRadius="0.2rem"
textAlign="center"
backgroundColor="var(--status-bad-color)"
>
{t('modelmanager:noModelsFound')}
</Text>
)}
{renderFoundModels()}
</Flex>
</Flex>
)}
</>
);
}

View File

@@ -1,93 +0,0 @@
// .chakra-accordion {
// display: grid;
// row-gap: 0.5rem;
// }
// .chakra-accordion__item {
// border: none;
// }
// button {
// border-radius: 0.3rem;
// &[aria-expanded='true'] {
// // background-color: var(--tab-hover-color);
// border-radius: 0.3rem;
// }
// }
.model-list-accordion {
outline: none;
padding: 0.25rem;
button {
padding: 0;
margin: 0;
&:hover {
background-color: unset;
}
}
div {
border: none;
}
.model-list-button {
display: flex;
flex-direction: row;
row-gap: 0.5rem;
justify-content: space-between;
align-items: center;
width: 100%;
}
.model-list-header-hint {
color: var(--text-color-secondary);
font-weight: normal;
}
.model-list-list {
display: flex;
flex-direction: column;
row-gap: 0.5rem;
.model-list-item {
display: flex;
column-gap: 0.5rem;
width: 100%;
justify-content: space-between;
align-items: center;
.model-list-item-name {
}
.model-list-item-description {
font-size: 0.9rem;
}
.model-list-item-status {
&.active {
color: var(--status-good-color);
}
&.cached {
color: var(--status-working-color);
}
&.not-loaded {
color: var(--text-color-secondary);
}
}
.model-list-item-load-btn {
button {
padding: 0.5rem;
background-color: var(--btn-base-color);
color: var(--text-color);
border-radius: 0.2rem;
&:hover {
background-color: var(--btn-base-color-hover);
}
}
}
}
}
}

View File

@@ -1,117 +0,0 @@
import {
Button,
Tooltip,
Spacer,
Accordion,
AccordionItem,
AccordionButton,
AccordionPanel,
AccordionIcon,
Text,
} from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import _ from 'lodash';
import { ModelStatus } from 'app/invokeai';
import { requestModelChange } from 'app/socketio/actions';
import { RootState } from 'app/store';
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
import { SystemState } from 'features/system/store/systemSlice';
import { useTranslation } from 'react-i18next';
type ModelListItemProps = {
name: string;
status: ModelStatus;
description: string;
};
const ModelListItem = (props: ModelListItemProps) => {
const { isProcessing, isConnected } = useAppSelector(
(state: RootState) => state.system
);
const dispatch = useAppDispatch();
const { name, status, description } = props;
const handleChangeModel = () => {
dispatch(requestModelChange(name));
};
const { t } = useTranslation();
return (
<div className="model-list-item">
<Tooltip label={description} hasArrow placement="bottom">
<div className="model-list-item-name">{name}</div>
</Tooltip>
<Spacer />
<div className={`model-list-item-status ${status.split(' ').join('-')}`}>
{status}
</div>
<div className="model-list-item-load-btn">
<Button
size={'sm'}
onClick={handleChangeModel}
isDisabled={status === 'active' || isProcessing || !isConnected}
>
{t('common:load')}
</Button>
</div>
</div>
);
};
const modelListSelector = createSelector(
(state: RootState) => state.system,
(system: SystemState) => {
const models = _.map(system.model_list, (model, key) => {
return { name: key, ...model };
});
const activeModel = models.find((model) => model.status === 'active');
return {
models,
activeModel: activeModel,
};
}
);
const ModelList = () => {
const { models } = useAppSelector(modelListSelector);
const { t } = useTranslation();
return (
<Accordion
allowToggle
className="model-list-accordion"
variant={'unstyled'}
>
<AccordionItem>
<AccordionButton>
<div className="model-list-button">
<Text
fontSize="sm"
fontWeight="bold"
color="var(--text-color-secondary)"
>
{t('settings:models')}
</Text>
<AccordionIcon />
</div>
</AccordionButton>
<AccordionPanel>
<div className="model-list-list">
{models.map((model, i) => (
<ModelListItem
key={i}
name={model.name}
status={model.status}
description={model.description}
/>
))}
</div>
</AccordionPanel>
</AccordionItem>
</Accordion>
);
};
export default ModelList;

View File

@@ -26,7 +26,6 @@ import {
setShouldDisplayGuides,
setShouldDisplayInProgressType,
} from 'features/system/store/systemSlice';
import ModelList from './ModelList';
import { IN_PROGRESS_IMAGE_TYPES } from 'app/constants';
import IAISwitch from 'common/components/IAISwitch';
import IAISelect from 'common/components/IAISelect';
@@ -139,9 +138,6 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
<ModalCloseButton className="modal-close-btn" />
<ModalBody className="settings-modal-content">
<div className="settings-modal-items">
<div className="settings-modal-item">
<ModelList />
</div>
<div
className="settings-modal-item"
style={{ gridAutoFlow: 'row', rowGap: '0.5rem' }}

View File

@@ -1,12 +1,6 @@
import { Link } from '@chakra-ui/react';
import {
FaGithub,
FaDiscord,
FaBug,
FaKeyboard,
FaWrench,
} from 'react-icons/fa';
import { FaGithub, FaDiscord, FaBug, FaKeyboard, FaCube } from 'react-icons/fa';
import InvokeAILogo from 'assets/images/logo.png';
import IAIIconButton from 'common/components/IAIIconButton';
@@ -17,9 +11,12 @@ import SettingsModal from './SettingsModal/SettingsModal';
import StatusIndicator from './StatusIndicator';
import ThemeChanger from './ThemeChanger';
import ModelSelect from './ModelSelect';
import ModelManagerModal from './ModelManager/ModelManagerModal';
import LanguagePicker from './LanguagePicker';
import { useTranslation } from 'react-i18next';
import { MdSettings } from 'react-icons/md';
/**
* Header, includes color mode toggle, settings button, status message.
@@ -41,6 +38,18 @@ const SiteHeader = () => {
<ModelSelect />
<ModelManagerModal>
<IAIIconButton
aria-label={t('modelmanager:modelManager')}
tooltip={t('modelmanager:modelManager')}
size={'sm'}
variant="link"
data-variant="link"
fontSize={20}
icon={<FaCube />}
/>
</ModelManagerModal>
<HotkeysModal>
<IAIIconButton
aria-label={t('common:hotkeysLabel')}
@@ -105,9 +114,9 @@ const SiteHeader = () => {
tooltip={t('common:settingsLabel')}
variant="link"
data-variant="link"
fontSize={20}
fontSize={22}
size={'sm'}
icon={<FaWrench />}
icon={<MdSettings />}
/>
</SettingsModal>
</div>

View File

@@ -47,6 +47,9 @@ export interface SystemState
saveIntermediatesInterval: number;
enableImageDebugging: boolean;
toastQueue: UseToastOptions[];
searchFolder: string | null;
foundModels: InvokeAI.FoundModel[] | null;
openModel: string | null;
}
const initialSystemState: SystemState = {
@@ -82,6 +85,9 @@ const initialSystemState: SystemState = {
saveIntermediatesInterval: 5,
enableImageDebugging: false,
toastQueue: [],
searchFolder: null,
foundModels: null,
openModel: null,
};
export const systemSlice = createSlice({
@@ -225,6 +231,18 @@ export const systemSlice = createSlice({
state.currentStatus = action.payload;
state.currentStatusHasSteps = false;
},
setSearchFolder: (state, action: PayloadAction<string | null>) => {
state.searchFolder = action.payload;
},
setFoundModels: (
state,
action: PayloadAction<InvokeAI.FoundModel[] | null>
) => {
state.foundModels = action.payload;
},
setOpenModel: (state, action: PayloadAction<string | null>) => {
state.openModel = action.payload;
},
},
});
@@ -253,6 +271,9 @@ export const {
addToast,
clearToastQueue,
setProcessingIndeterminateTask,
setSearchFolder,
setFoundModels,
setOpenModel,
} = systemSlice.actions;
export default systemSlice.reducer;

View File

@@ -8,6 +8,7 @@ import gallery from '../public/locales/gallery/en.json';
import toast from '../public/locales/toast/en.json';
import hotkeys from '../public/locales/hotkeys/en.json';
import settings from '../public/locales/settings/en.json';
import modelmanager from '../public/locales/modelmanager/en.json';
declare module 'i18next' {
// Extend CustomTypeOptions
@@ -23,6 +24,7 @@ declare module 'i18next' {
toast: typeof toast;
hotkeys: typeof hotkeys;
settings: typeof settings;
modelmanager: typeof modelmanager;
};
// Never Return Null
returnNull: false;

View File

@@ -18,6 +18,7 @@ i18n
'toast',
'hotkeys',
'settings',
'modelmanager',
],
backend: {
loadPath: '/locales/{{ns}}/{{lng}}.json',

View File

@@ -89,6 +89,7 @@
--status-working-glow: rgb(255, 160, 55);
--status-bad-color: rgb(255, 90, 90);
--status-bad-glow: rgb(255, 40, 40);
--notice-color: rgb(130, 71, 19);
// Settings Modal
--settings-modal-bg: rgb(30, 32, 42);
@@ -132,4 +133,8 @@
// Checkerboard
--checkboard-dots-color: rgb(35, 35, 39);
// Scrollbar
--scrollbar-color: var(--accent-color);
--scrollbar-color-hover: var(--accent-color-bright);
}

View File

@@ -87,6 +87,7 @@
--status-working-glow: rgb(255, 160, 55);
--status-bad-color: rgb(255, 90, 90);
--status-bad-glow: rgb(255, 40, 40);
--notice-color: rgb(130, 71, 19);
// Settings Modal
--settings-modal-bg: rgb(30, 32, 42);
@@ -130,4 +131,8 @@
//Checkerboard
--checkboard-dots-color: rgb(35, 35, 39);
// Scrollbar
--scrollbar-color: var(--accent-color);
--scrollbar-color-hover: var(--accent-color-bright);
}

View File

@@ -84,6 +84,7 @@
--status-working-glow: var(--background-color);
--status-bad-color: rgb(202, 0, 0);
--status-bad-glow: var(--background-color);
--notice-color: rgb(255, 71, 90);
// Settings Modal
--settings-modal-bg: rgb(202, 204, 206);
@@ -127,4 +128,8 @@
// Checkerboard
--checkboard-dots-color: rgb(160, 160, 172);
// Scrollbar
--scrollbar-color: rgb(180, 180, 184);
--scrollbar-color-hover: rgb(150, 150, 154);
}

View File

@@ -14,3 +14,32 @@
// var(--background-color-secondary);
// background-size: 64px 64px;
// }
* {
scrollbar-width: thick; /* none | auto */
scrollbar-color: var(--scrollbar-color) transparent;
}
*::-webkit-scrollbar {
width: 8px; // Vertical Scrollbar Width
height: 8px; // Horizontal Scrollbar Height
}
*::-webkit-scrollbar-track {
background: transparent;
}
*::-webkit-scrollbar-thumb {
background: var(--scrollbar-color);
border-radius: 8px;
border: calc(8px / 4) solid var(--scrollbar-color);
}
*::-webkit-scrollbar-thumb:hover {
background: var(--scrollbar-color-hover);
border: calc(8px / 4) solid var(--scrollbar-color-hover);
}
::-webkit-scrollbar-button {
background: transparent;
}

View File

@@ -16,7 +16,7 @@
@use '../features/system/components/SiteHeader.scss';
@use '../features/system/components/StatusIndicator.scss';
@use '../features/system/components/SettingsModal/SettingsModal.scss';
@use '../features/system/components/SettingsModal/ModelList.scss';
@use '../features/system/components/ModelManager/AddModel.scss';
@use '../features/system/components/HotkeysModal/HotkeysModal.scss';
@use '../features/system/components/Console.scss';

View File

@@ -2331,6 +2331,11 @@ deep-is@^0.1.3, deep-is@~0.1.3:
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
deepmerge@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
defaults@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a"
@@ -2946,6 +2951,19 @@ focus-lock@^0.11.2:
dependencies:
tslib "^2.0.3"
formik@^2.2.9:
version "2.2.9"
resolved "https://registry.yarnpkg.com/formik/-/formik-2.2.9.tgz#8594ba9c5e2e5cf1f42c5704128e119fc46232d0"
integrity sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==
dependencies:
deepmerge "^2.1.1"
hoist-non-react-statics "^3.3.0"
lodash "^4.17.21"
lodash-es "^4.17.21"
react-fast-compare "^2.0.1"
tiny-warning "^1.0.2"
tslib "^1.10.0"
framer-motion@^7.2.1:
version "7.6.9"
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-7.6.9.tgz#d2c8ca8b97580aa00f7c6e2b616da241bd2ce8e6"
@@ -3445,6 +3463,11 @@ locate-path@^6.0.0:
dependencies:
p-locate "^5.0.0"
lodash-es@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
@@ -4021,6 +4044,11 @@ react-fast-compare@3.2.0:
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==
react-fast-compare@^2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
react-focus-lock@^2.9.1:
version "2.9.2"
resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.9.2.tgz#a57dfd7c493e5a030d87f161c96ffd082bd920f2"
@@ -4602,6 +4630,11 @@ tiny-invariant@^1.0.6:
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642"
integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==
tiny-warning@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@@ -4671,7 +4704,7 @@ tslib@2.4.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
tslib@^1.8.1, tslib@^1.9.3:
tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.3:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==

View File

@@ -3,7 +3,7 @@
cd "$(dirname "$0")"
VERSION=$(grep ^VERSION ../setup.py | awk '{ print $3 }' | sed "s/'//g" )
VERSION="$VERSION-p2"
VERSION="$VERSION-p3"
echo "Be certain that you're in the 'installer' directory before continuing."
read -p "Press any key to continue, or CTRL-C to exit..."

View File

@@ -23,6 +23,7 @@ from omegaconf.errors import ConfigAttributeError
from ldm.util import instantiate_from_config, ask_user
from ldm.invoke.globals import Globals
from picklescan.scanner import scan_file_path
from pathlib import Path
DEFAULT_MAX_MODELS=2
@@ -133,10 +134,13 @@ class ModelCache(object):
'''
models = {}
for name in self.config:
try:
description = self.config[name].description
except ConfigAttributeError:
description = '<no description>'
description = self.config[name].description if 'description' in self.config[name] else '<no description>'
weights = self.config[name].weights if 'weights' in self.config[name] else '<no weights>'
config = self.config[name].config if 'config' in self.config[name] else '<no config>'
width = self.config[name].width if 'width' in self.config[name] else 512
height = self.config[name].height if 'height' in self.config[name] else 512
default = self.config[name].default if 'default' in self.config[name] else False
vae = self.config[name].vae if 'vae' in self.config[name] else '<no vae>'
if self.current_model == name:
status = 'active'
@@ -147,7 +151,13 @@ class ModelCache(object):
models[name]={
'status' : status,
'description' : description
'description' : description,
'weights': weights,
'config': config,
'width': width,
'height': height,
'vae': vae,
'default': default
}
return models
@@ -186,6 +196,8 @@ class ModelCache(object):
config = omega[model_name] if model_name in omega else {}
for field in model_attributes:
if field == 'weights':
field.replace('\\', '/')
config[field] = model_attributes[field]
omega[model_name] = config
@@ -311,6 +323,22 @@ class ModelCache(object):
sys.exit()
else:
print('>> Model Scanned. OK!!')
def search_models(self, search_folder):
print(f'>> Finding Models In: {search_folder}')
models_folder = Path(search_folder).glob('**/*.ckpt')
files = [x for x in models_folder if x.is_file()]
found_models = []
for file in files:
found_models.append({
'name': file.stem,
'location': str(file.resolve()).replace('\\', '/')
})
return search_folder, found_models
def _make_cache_room(self) -> None:
num_loaded_models = len(self.models)