diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 02bc10df90..0f0b953be7 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -42,6 +42,21 @@ Please provide steps on how to test changes, any hardware or software specifications as well as any other pertinent information. --> +## Merge Plan + + + ## Added/updated tests? - [ ] Yes diff --git a/docs/installation/020_INSTALL_MANUAL.md b/docs/installation/020_INSTALL_MANUAL.md index 0ddf1bca68..b395405ba3 100644 --- a/docs/installation/020_INSTALL_MANUAL.md +++ b/docs/installation/020_INSTALL_MANUAL.md @@ -293,6 +293,19 @@ manager, please follow these steps: ## Developer Install +!!! warning + + InvokeAI uses a SQLite database. By running on `main`, you accept responsibility for your database. This + means making regular backups (especially before pulling) and/or fixing it yourself in the event that a + PR introduces a schema change. + + If you don't need persistent backend storage, you can use an ephemeral in-memory database by setting + `use_memory_db: true` under `Path:` in your `invokeai.yaml` file. + + If this is untenable, you should run the application via the official installer or a manual install of the + python package from pypi. These releases will not break your database. + + If you have an interest in how InvokeAI works, or you would like to add features or bugfixes, you are encouraged to install the source code for InvokeAI. For this to work, you will need to install the @@ -388,3 +401,5 @@ environment variable INVOKEAI_ROOT to point to the installation directory. Note that if you run into problems with the Conda installation, the InvokeAI staff will **not** be able to help you out. Caveat Emptor! + +[dev-chat]: https://discord.com/channels/1020123559063990373/1049495067846524939 \ No newline at end of file diff --git a/docs/javascripts/init_kapa_widget.js b/docs/javascripts/init_kapa_widget.js new file mode 100644 index 0000000000..f22e276b5a --- /dev/null +++ b/docs/javascripts/init_kapa_widget.js @@ -0,0 +1,10 @@ +document.addEventListener("DOMContentLoaded", function () { + var script = document.createElement("script"); + script.src = "https://widget.kapa.ai/kapa-widget.bundle.js"; + script.setAttribute("data-website-id", "b5973bb1-476b-451e-8cf4-98de86745a10"); + script.setAttribute("data-project-name", "Invoke.AI"); + script.setAttribute("data-project-color", "#11213C"); + script.setAttribute("data-project-logo", "https://avatars.githubusercontent.com/u/113954515?s=280&v=4"); + script.async = true; + document.head.appendChild(script); +}); diff --git a/invokeai/app/invocations/image.py b/invokeai/app/invocations/image.py index 89209fed41..f729d60cdd 100644 --- a/invokeai/app/invocations/image.py +++ b/invokeai/app/invocations/image.py @@ -13,7 +13,15 @@ from invokeai.app.shared.fields import FieldDescriptions from invokeai.backend.image_util.invisible_watermark import InvisibleWatermark from invokeai.backend.image_util.safety_checker import SafetyChecker -from .baseinvocation import BaseInvocation, Input, InputField, InvocationContext, WithMetadata, invocation +from .baseinvocation import ( + BaseInvocation, + Classification, + Input, + InputField, + InvocationContext, + WithMetadata, + invocation, +) @invocation("show_image", title="Show Image", tags=["image"], category="image", version="1.0.0") @@ -421,6 +429,64 @@ class ImageBlurInvocation(BaseInvocation, WithMetadata): ) +@invocation( + "unsharp_mask", + title="Unsharp Mask", + tags=["image", "unsharp_mask"], + category="image", + version="1.2.0", + classification=Classification.Beta, +) +class UnsharpMaskInvocation(BaseInvocation, WithMetadata): + """Applies an unsharp mask filter to an image""" + + image: ImageField = InputField(description="The image to use") + radius: float = InputField(gt=0, description="Unsharp mask radius", default=2) + strength: float = InputField(ge=0, description="Unsharp mask strength", default=50) + + def pil_from_array(self, arr): + return Image.fromarray((arr * 255).astype("uint8")) + + def array_from_pil(self, img): + return numpy.array(img) / 255 + + def invoke(self, context: InvocationContext) -> ImageOutput: + image = context.services.images.get_pil_image(self.image.image_name) + mode = image.mode + + alpha_channel = image.getchannel("A") if mode == "RGBA" else None + image = image.convert("RGB") + image_blurred = self.array_from_pil(image.filter(ImageFilter.GaussianBlur(radius=self.radius))) + + image = self.array_from_pil(image) + image += (image - image_blurred) * (self.strength / 100.0) + image = numpy.clip(image, 0, 1) + image = self.pil_from_array(image) + + image = image.convert(mode) + + # Make the image RGBA if we had a source alpha channel + if alpha_channel is not None: + image.putalpha(alpha_channel) + + image_dto = context.services.images.create( + image=image, + image_origin=ResourceOrigin.INTERNAL, + image_category=ImageCategory.GENERAL, + node_id=self.id, + session_id=context.graph_execution_state_id, + is_intermediate=self.is_intermediate, + metadata=self.metadata, + workflow=context.workflow, + ) + + return ImageOutput( + image=ImageField(image_name=image_dto.image_name), + width=image.width, + height=image.height, + ) + + PIL_RESAMPLING_MODES = Literal[ "nearest", "box", diff --git a/invokeai/app/invocations/tiles.py b/invokeai/app/invocations/tiles.py index c0582986a8..cbf63ab169 100644 --- a/invokeai/app/invocations/tiles.py +++ b/invokeai/app/invocations/tiles.py @@ -38,7 +38,14 @@ class CalculateImageTilesOutput(BaseInvocationOutput): tiles: list[Tile] = OutputField(description="The tiles coordinates that cover a particular image shape.") -@invocation("calculate_image_tiles", title="Calculate Image Tiles", tags=["tiles"], category="tiles", version="1.0.0") +@invocation( + "calculate_image_tiles", + title="Calculate Image Tiles", + tags=["tiles"], + category="tiles", + version="1.0.0", + classification=Classification.Beta, +) class CalculateImageTilesInvocation(BaseInvocation): """Calculate the coordinates and overlaps of tiles that cover a target image shape.""" diff --git a/invokeai/app/services/shared/sqlite_migrator/migrations/migration_2.py b/invokeai/app/services/shared/sqlite_migrator/migrations/migration_2.py index 9efd2a1283..9b9dedcc58 100644 --- a/invokeai/app/services/shared/sqlite_migrator/migrations/migration_2.py +++ b/invokeai/app/services/shared/sqlite_migrator/migrations/migration_2.py @@ -1,10 +1,15 @@ import sqlite3 from logging import Logger +from pydantic import ValidationError from tqdm import tqdm from invokeai.app.services.image_files.image_files_base import ImageFileStorageBase +from invokeai.app.services.image_files.image_files_common import ImageFileNotFoundException from invokeai.app.services.shared.sqlite_migrator.sqlite_migrator_common import Migration +from invokeai.app.services.workflow_records.workflow_records_common import ( + UnsafeWorkflowWithVersionValidator, +) class Migration2Callback: @@ -134,7 +139,7 @@ class Migration2Callback: This migrate callback checks each image for the presence of an embedded workflow, then updates its entry in the database accordingly. """ - # Get the total number of images and chunk it into pages + # Get all image names cursor.execute("SELECT image_name FROM images") image_names: list[str] = [image[0] for image in cursor.fetchall()] total_image_names = len(image_names) @@ -149,8 +154,17 @@ class Migration2Callback: pbar = tqdm(image_names) for idx, image_name in enumerate(pbar): pbar.set_description(f"Checking image {idx + 1}/{total_image_names} for workflow") - pil_image = self._image_files.get(image_name) + try: + pil_image = self._image_files.get(image_name) + except ImageFileNotFoundException: + self._logger.warning(f"Image {image_name} not found, skipping") + continue if "invokeai_workflow" in pil_image.info: + try: + UnsafeWorkflowWithVersionValidator.validate_json(pil_image.info.get("invokeai_workflow", "")) + except ValidationError: + self._logger.warning(f"Image {image_name} has invalid embedded workflow, skipping") + continue to_migrate.append((True, image_name)) self._logger.info(f"Adding {len(to_migrate)} embedded workflows to database") diff --git a/invokeai/app/services/workflow_records/workflow_records_common.py b/invokeai/app/services/workflow_records/workflow_records_common.py index ffc98bb786..e7f3d4295f 100644 --- a/invokeai/app/services/workflow_records/workflow_records_common.py +++ b/invokeai/app/services/workflow_records/workflow_records_common.py @@ -65,12 +65,24 @@ class WorkflowWithoutID(BaseModel): nodes: list[dict[str, JsonValue]] = Field(description="The nodes of the workflow.") edges: list[dict[str, JsonValue]] = Field(description="The edges of the workflow.") - model_config = ConfigDict(extra="forbid") + model_config = ConfigDict(extra="ignore") WorkflowWithoutIDValidator = TypeAdapter(WorkflowWithoutID) +class UnsafeWorkflowWithVersion(BaseModel): + """ + This utility model only requires a workflow to have a valid version string. + It is used to validate a workflow version without having to validate the entire workflow. + """ + + meta: WorkflowMeta = Field(description="The meta of the workflow.") + + +UnsafeWorkflowWithVersionValidator = TypeAdapter(UnsafeWorkflowWithVersion) + + class Workflow(WorkflowWithoutID): id: str = Field(description="The id of the workflow.") diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index ec257ee044..f5f3f434f5 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -950,9 +950,9 @@ "problemSettingTitle": "Problem Setting Title", "reloadNodeTemplates": "Reload Node Templates", "removeLinearView": "Remove from Linear View", - "resetWorkflow": "Reset Workflow Editor", - "resetWorkflowDesc": "Are you sure you want to reset the Workflow Editor?", - "resetWorkflowDesc2": "Resetting the Workflow Editor will clear all nodes, edges and workflow details. Saved workflows will not be affected.", + "newWorkflow": "New Workflow", + "newWorkflowDesc": "Create a new workflow?", + "newWorkflowDesc2": "Your current workflow has unsaved changes.", "scheduler": "Scheduler", "schedulerDescription": "TODO", "sDXLMainModelField": "SDXL Model", @@ -1634,10 +1634,10 @@ "userWorkflows": "My Workflows", "defaultWorkflows": "Default Workflows", "openWorkflow": "Open Workflow", - "uploadWorkflow": "Upload Workflow", + "uploadWorkflow": "Load from File", "deleteWorkflow": "Delete Workflow", "unnamedWorkflow": "Unnamed Workflow", - "downloadWorkflow": "Download Workflow", + "downloadWorkflow": "Save to File", "saveWorkflow": "Save Workflow", "saveWorkflowAs": "Save Workflow As", "savingWorkflow": "Saving Workflow...", @@ -1652,7 +1652,7 @@ "searchWorkflows": "Search Workflows", "clearWorkflowSearchFilter": "Clear Workflow Search Filter", "workflowName": "Workflow Name", - "workflowEditorReset": "Workflow Editor Reset", + "newWorkflowCreated": "New Workflow Created", "workflowEditorMenu": "Workflow Editor Menu", "workflowIsOpen": "Workflow is Open" }, diff --git a/invokeai/frontend/web/public/locales/it.json b/invokeai/frontend/web/public/locales/it.json index 31eea70368..c2eebedf77 100644 --- a/invokeai/frontend/web/public/locales/it.json +++ b/invokeai/frontend/web/public/locales/it.json @@ -104,7 +104,16 @@ "copyError": "$t(gallery.copy) Errore", "input": "Ingresso", "notInstalled": "Non $t(common.installed)", - "unknownError": "Errore sconosciuto" + "unknownError": "Errore sconosciuto", + "updated": "Aggiornato", + "save": "Salva", + "created": "Creato", + "prevPage": "Pagina precedente", + "delete": "Elimina", + "orderBy": "Ordinato per", + "nextPage": "Pagina successiva", + "saveAs": "Salva come", + "unsaved": "Non salvato" }, "gallery": { "generations": "Generazioni", @@ -763,7 +772,10 @@ "setIPAdapterImage": "Imposta come immagine per l'Adattatore IP", "problemSavingMaskDesc": "Impossibile salvare la maschera", "setAsCanvasInitialImage": "Imposta come immagine iniziale della tela", - "invalidUpload": "Caricamento non valido" + "invalidUpload": "Caricamento non valido", + "problemDeletingWorkflow": "Problema durante l'eliminazione del flusso di lavoro", + "workflowDeleted": "Flusso di lavoro eliminato", + "problemRetrievingWorkflow": "Problema nel recupero del flusso di lavoro" }, "tooltip": { "feature": { @@ -886,11 +898,11 @@ "zoomInNodes": "Ingrandire", "fitViewportNodes": "Adatta vista", "showGraphNodes": "Mostra sovrapposizione grafico", - "resetWorkflowDesc2": "Reimpostare il flusso di lavoro cancellerà tutti i nodi, i bordi e i dettagli del flusso di lavoro.", + "resetWorkflowDesc2": "Il ripristino dell'editor del flusso di lavoro cancellerà tutti i nodi, le connessioni e i dettagli del flusso di lavoro. I flussi di lavoro salvati non saranno interessati.", "reloadNodeTemplates": "Ricarica i modelli di nodo", "loadWorkflow": "Importa flusso di lavoro JSON", - "resetWorkflow": "Reimposta flusso di lavoro", - "resetWorkflowDesc": "Sei sicuro di voler reimpostare questo flusso di lavoro?", + "resetWorkflow": "Reimposta l'editor del flusso di lavoro", + "resetWorkflowDesc": "Sei sicuro di voler reimpostare l'editor del flusso di lavoro?", "downloadWorkflow": "Esporta flusso di lavoro JSON", "scheduler": "Campionatore", "addNode": "Aggiungi nodo", @@ -1080,25 +1092,27 @@ "collectionOrScalarFieldType": "{{name}} Raccolta|Scalare", "nodeVersion": "Versione Nodo", "inputFieldTypeParseError": "Impossibile analizzare il tipo di campo di input {{node}}.{{field}} ({{message}})", - "unsupportedArrayItemType": "tipo di elemento dell'array non supportato \"{{type}}\"", + "unsupportedArrayItemType": "Tipo di elemento dell'array non supportato \"{{type}}\"", "targetNodeFieldDoesNotExist": "Connessione non valida: il campo di destinazione/input {{node}}.{{field}} non esiste", "unsupportedMismatchedUnion": "tipo CollectionOrScalar non corrispondente con tipi di base {{firstType}} e {{secondType}}", "allNodesUpdated": "Tutti i nodi sono aggiornati", "sourceNodeDoesNotExist": "Connessione non valida: il nodo di origine/output {{node}} non esiste", - "unableToExtractEnumOptions": "impossibile estrarre le opzioni enum", - "unableToParseFieldType": "impossibile analizzare il tipo di campo", + "unableToExtractEnumOptions": "Impossibile estrarre le opzioni enum", + "unableToParseFieldType": "Impossibile analizzare il tipo di campo", "unrecognizedWorkflowVersion": "Versione dello schema del flusso di lavoro non riconosciuta {{version}}", "outputFieldTypeParseError": "Impossibile analizzare il tipo di campo di output {{node}}.{{field}} ({{message}})", "sourceNodeFieldDoesNotExist": "Connessione non valida: il campo di origine/output {{node}}.{{field}} non esiste", "unableToGetWorkflowVersion": "Impossibile ottenere la versione dello schema del flusso di lavoro", "nodePack": "Pacchetto di nodi", - "unableToExtractSchemaNameFromRef": "impossibile estrarre il nome dello schema dal riferimento", + "unableToExtractSchemaNameFromRef": "Impossibile estrarre il nome dello schema dal riferimento", "unknownOutput": "Output sconosciuto: {{name}}", "unknownNodeType": "Tipo di nodo sconosciuto", "targetNodeDoesNotExist": "Connessione non valida: il nodo di destinazione/input {{node}} non esiste", "unknownFieldType": "$t(nodes.unknownField) tipo: {{type}}", "deletedInvalidEdge": "Eliminata connessione non valida {{source}} -> {{target}}", - "unknownInput": "Input sconosciuto: {{name}}" + "unknownInput": "Input sconosciuto: {{name}}", + "prototypeDesc": "Questa invocazione è un prototipo. Potrebbe subire modifiche sostanziali durante gli aggiornamenti dell'app e potrebbe essere rimossa in qualsiasi momento.", + "betaDesc": "Questa invocazione è in versione beta. Fino a quando non sarà stabile, potrebbe subire modifiche importanti durante gli aggiornamenti dell'app. Abbiamo intenzione di supportare questa invocazione a lungo termine." }, "boards": { "autoAddBoard": "Aggiungi automaticamente bacheca", @@ -1594,5 +1608,34 @@ "hrf": "Correzione Alta Risoluzione", "hrfStrength": "Forza della Correzione Alta Risoluzione", "strengthTooltip": "Valori più bassi comportano meno dettagli, il che può ridurre potenziali artefatti." + }, + "workflows": { + "saveWorkflowAs": "Salva flusso di lavoro come", + "workflowEditorMenu": "Menu dell'editor del flusso di lavoro", + "noSystemWorkflows": "Nessun flusso di lavoro del sistema", + "workflowName": "Nome del flusso di lavoro", + "noUserWorkflows": "Nessun flusso di lavoro utente", + "defaultWorkflows": "Flussi di lavoro predefiniti", + "saveWorkflow": "Salva flusso di lavoro", + "openWorkflow": "Apri flusso di lavoro", + "clearWorkflowSearchFilter": "Cancella il filtro di ricerca del flusso di lavoro", + "workflowEditorReset": "Reimpostazione dell'editor del flusso di lavoro", + "workflowLibrary": "Libreria", + "noRecentWorkflows": "Nessun flusso di lavoro recente", + "workflowSaved": "Flusso di lavoro salvato", + "workflowIsOpen": "Il flusso di lavoro è aperto", + "unnamedWorkflow": "Flusso di lavoro senza nome", + "savingWorkflow": "Salvataggio del flusso di lavoro...", + "problemLoading": "Problema durante il caricamento dei flussi di lavoro", + "loading": "Caricamento dei flussi di lavoro", + "searchWorkflows": "Cerca flussi di lavoro", + "problemSavingWorkflow": "Problema durante il salvataggio del flusso di lavoro", + "deleteWorkflow": "Elimina flusso di lavoro", + "workflows": "Flussi di lavoro", + "noDescription": "Nessuna descrizione", + "userWorkflows": "I miei flussi di lavoro" + }, + "app": { + "storeNotInitialized": "Il negozio non è inizializzato" } } diff --git a/invokeai/frontend/web/public/locales/ru.json b/invokeai/frontend/web/public/locales/ru.json index 22df944086..901d0520d5 100644 --- a/invokeai/frontend/web/public/locales/ru.json +++ b/invokeai/frontend/web/public/locales/ru.json @@ -51,23 +51,23 @@ "statusConvertingModel": "Конвертация модели", "cancel": "Отменить", "accept": "Принять", - "langUkranian": "Украинский", - "langEnglish": "Английский", + "langUkranian": "Украї́нська", + "langEnglish": "English", "postprocessing": "Постобработка", - "langArabic": "Арабский", - "langSpanish": "Испанский", - "langSimplifiedChinese": "Китайский (упрощенный)", - "langDutch": "Нидерландский", - "langFrench": "Французский", - "langGerman": "Немецкий", - "langHebrew": "Иврит", - "langItalian": "Итальянский", - "langJapanese": "Японский", - "langKorean": "Корейский", - "langPolish": "Польский", - "langPortuguese": "Португальский", + "langArabic": "العربية", + "langSpanish": "Español", + "langSimplifiedChinese": "简体中文", + "langDutch": "Nederlands", + "langFrench": "Français", + "langGerman": "German", + "langHebrew": "Hebrew", + "langItalian": "Italiano", + "langJapanese": "日本語", + "langKorean": "한국어", + "langPolish": "Polski", + "langPortuguese": "Português", "txt2img": "Текст в изображение (txt2img)", - "langBrPortuguese": "Португальский (Бразилия)", + "langBrPortuguese": "Português do Brasil", "linear": "Линейная обработка", "dontAskMeAgain": "Больше не спрашивать", "areYouSure": "Вы уверены?", @@ -82,7 +82,46 @@ "darkMode": "Темная тема", "nodeEditor": "Редактор Нодов (Узлов)", "controlNet": "Controlnet", - "advanced": "Расширенные" + "advanced": "Расширенные", + "t2iAdapter": "T2I Adapter", + "checkpoint": "Checkpoint", + "format": "Формат", + "unknown": "Неизвестно", + "folder": "Папка", + "inpaint": "Перерисовать", + "updated": "Обновлен", + "on": "На", + "save": "Сохранить", + "created": "Создано", + "error": "Ошибка", + "prevPage": "Предыдущая страница", + "simple": "Простой", + "ipAdapter": "IP Adapter", + "controlAdapter": "Адаптер контроля", + "installed": "Установлено", + "ai": "ИИ", + "auto": "Авто", + "file": "Файл", + "delete": "Удалить", + "template": "Шаблон", + "outputs": "результаты", + "unknownError": "Неизвестная ошибка", + "statusProcessing": "Обработка", + "imageFailedToLoad": "Невозможно загрузить изображение", + "direction": "Направление", + "data": "Данные", + "somethingWentWrong": "Что-то пошло не так", + "safetensors": "Safetensors", + "outpaint": "Расширить изображение", + "orderBy": "Сортировать по", + "copyError": "Ошибка $t(gallery.copy)", + "learnMore": "Узнать больше", + "nextPage": "Следущая страница", + "saveAs": "Сохранить как", + "unsaved": "несохраненный", + "input": "Вход", + "details": "Детали", + "notInstalled": "Нет $t(common.installed)" }, "gallery": { "generations": "Генерации", @@ -102,7 +141,27 @@ "deleteImageBin": "Удаленные изображения будут отправлены в корзину вашей операционной системы.", "deleteImage": "Удалить изображение", "assets": "Ресурсы", - "autoAssignBoardOnClick": "Авто-назначение доски по клику" + "autoAssignBoardOnClick": "Авто-назначение доски по клику", + "deleteSelection": "Удалить выделенное", + "featuresWillReset": "Если вы удалите это изображение, эти функции будут немедленно сброшены.", + "problemDeletingImagesDesc": "Не удалось удалить одно или несколько изображений", + "loading": "Загрузка", + "unableToLoad": "Невозможно загрузить галерею", + "preparingDownload": "Подготовка к скачиванию", + "preparingDownloadFailed": "Проблема с подготовкой к скачиванию", + "image": "изображение", + "drop": "перебросить", + "problemDeletingImages": "Проблема с удалением изображений", + "downloadSelection": "Скачать выделенное", + "currentlyInUse": "В настоящее время это изображение используется в следующих функциях:", + "unstarImage": "Удалить из избранного", + "dropOrUpload": "$t(gallery.drop) или загрузить", + "copy": "Копировать", + "download": "Скачать", + "noImageSelected": "Изображение не выбрано", + "setCurrentImage": "Установить как текущее изображение", + "starImage": "Добавить в избранное", + "dropToUpload": "$t(gallery.drop) чтоб загрузить" }, "hotkeys": { "keyboardShortcuts": "Горячие клавиши", @@ -334,7 +393,7 @@ "config": "Файл конфигурации", "configValidationMsg": "Путь до файла конфигурации.", "modelLocation": "Расположение модели", - "modelLocationValidationMsg": "Путь до файла с моделью.", + "modelLocationValidationMsg": "Укажите путь к локальной папке, в которой хранится ваша модель Diffusers", "vaeLocation": "Расположение VAE", "vaeLocationValidationMsg": "Путь до файла VAE.", "width": "Ширина", @@ -377,7 +436,7 @@ "convertToDiffusersHelpText3": "Ваш файл контрольной точки НА ДИСКЕ будет УДАЛЕН, если он находится в корневой папке InvokeAI. Если он находится в пользовательском расположении, то он НЕ будет удален.", "vaeRepoID": "ID репозитория VAE", "mergedModelName": "Название объединенной модели", - "checkpointModels": "Checkpoints", + "checkpointModels": "Модели Checkpoint", "allModels": "Все модели", "addDiffuserModel": "Добавить Diffusers", "repo_id": "ID репозитория", @@ -413,7 +472,7 @@ "none": "пусто", "addDifference": "Добавить разницу", "vaeRepoIDValidationMsg": "Онлайн репозиторий VAE", - "convertToDiffusersHelpText2": "Этот процесс заменит вашу запись в Model Manager на версию той же модели в Diffusers.", + "convertToDiffusersHelpText2": "Этот процесс заменит вашу запись в менеджере моделей на версию той же модели в Diffusers.", "custom": "Пользовательский", "modelTwo": "Модель 2", "mergedModelSaveLocation": "Путь сохранения", @@ -444,14 +503,27 @@ "modelUpdateFailed": "Не удалось обновить модель", "modelConversionFailed": "Не удалось сконвертировать модель", "modelsMergeFailed": "Не удалось выполнить слияние моделей", - "loraModels": "LoRAs", - "onnxModels": "Onnx", - "oliveModels": "Olives" + "loraModels": "Модели LoRA", + "onnxModels": "Модели Onnx", + "oliveModels": "Модели Olives", + "conversionNotSupported": "Преобразование не поддерживается", + "noModels": "Нет моделей", + "predictionType": "Тип прогноза (для моделей Stable Diffusion 2.x и периодических моделей Stable Diffusion 1.x)", + "quickAdd": "Быстрое добавление", + "simpleModelDesc": "Укажите путь к локальной модели Diffusers , локальной модели checkpoint / safetensors, идентификатор репозитория HuggingFace или URL-адрес модели контрольной checkpoint / diffusers.", + "advanced": "Продвинутый", + "useCustomConfig": "Использовать кастомный конфиг", + "checkpointOrSafetensors": "$t(common.checkpoint) / $t(common.safetensors)", + "closeAdvanced": "Скрыть расширенные", + "modelType": "Тип модели", + "customConfigFileLocation": "Расположение пользовательского файла конфигурации", + "vaePrecision": "Точность VAE", + "noModelSelected": "Модель не выбрана" }, "parameters": { "images": "Изображения", "steps": "Шаги", - "cfgScale": "Уровень CFG", + "cfgScale": "Точность следования запросу (CFG)", "width": "Ширина", "height": "Высота", "seed": "Сид", @@ -471,7 +543,7 @@ "upscaleImage": "Увеличить изображение", "scale": "Масштаб", "otherOptions": "Другие параметры", - "seamlessTiling": "Бесшовный узор", + "seamlessTiling": "Бесшовность", "hiresOptim": "Оптимизация High Res", "imageFit": "Уместить изображение", "codeformerFidelity": "Точность", @@ -504,7 +576,8 @@ "immediate": "Отменить немедленно", "schedule": "Отменить после текущей итерации", "isScheduled": "Отмена", - "setType": "Установить тип отмены" + "setType": "Установить тип отмены", + "cancel": "Отмена" }, "general": "Основное", "hiresStrength": "Сила High Res", @@ -516,8 +589,8 @@ "copyImage": "Скопировать изображение", "showPreview": "Показать предпросмотр", "noiseSettings": "Шум", - "seamlessXAxis": "Ось X", - "seamlessYAxis": "Ось Y", + "seamlessXAxis": "Горизонтальная", + "seamlessYAxis": "Вертикальная", "scheduler": "Планировщик", "boundingBoxWidth": "Ширина ограничивающей рамки", "boundingBoxHeight": "Высота ограничивающей рамки", @@ -534,7 +607,51 @@ "coherenceSteps": "Шагов", "coherencePassHeader": "Порог Coherence", "coherenceStrength": "Сила", - "compositingSettingsHeader": "Настройки компоновки" + "compositingSettingsHeader": "Настройки компоновки", + "invoke": { + "noNodesInGraph": "Нет узлов в графе", + "noModelSelected": "Модель не выбрана", + "noPrompts": "Подсказки не создаются", + "systemBusy": "Система занята", + "noInitialImageSelected": "Исходное изображение не выбрано", + "missingInputForField": "{{nodeLabel}} -> {{fieldLabel}} отсутствует ввод", + "noControlImageForControlAdapter": "Адаптер контроля #{{number}} не имеет изображения", + "noModelForControlAdapter": "Не выбрана модель адаптера контроля #{{number}}.", + "unableToInvoke": "Невозможно вызвать", + "incompatibleBaseModelForControlAdapter": "Модель контрольного адаптера №{{number}} недействительна для основной модели.", + "systemDisconnected": "Система отключена", + "missingNodeTemplate": "Отсутствует шаблон узла", + "readyToInvoke": "Готово к вызову", + "missingFieldTemplate": "Отсутствует шаблон поля", + "addingImagesTo": "Добавление изображений в" + }, + "seamlessX&Y": "Бесшовный X & Y", + "isAllowedToUpscale": { + "useX2Model": "Изображение слишком велико для увеличения с помощью модели x4. Используйте модель x2", + "tooLarge": "Изображение слишком велико для увеличения. Выберите изображение меньшего размера" + }, + "aspectRatioFree": "Свободное", + "maskEdge": "Край маски", + "cpuNoise": "CPU шум", + "cfgRescaleMultiplier": "Множитель масштабирования CFG", + "cfgRescale": "Изменение масштаба CFG", + "patchmatchDownScaleSize": "уменьшить", + "gpuNoise": "GPU шум", + "seamlessX": "Бесшовный X", + "useCpuNoise": "Использовать шум CPU", + "clipSkipWithLayerCount": "CLIP пропуск {{layerCount}}", + "seamlessY": "Бесшовный Y", + "manualSeed": "Указанный сид", + "imageActions": "Действия с изображениями", + "randomSeed": "Случайный", + "iterations": "Кол-во", + "iterationsWithCount_one": "{{count}} Интеграция", + "iterationsWithCount_few": "{{count}} Итерации", + "iterationsWithCount_many": "{{count}} Итераций", + "useSize": "Использовать размер", + "unmasked": "Без маски", + "enableNoiseSettings": "Включить настройки шума", + "coherenceMode": "Режим" }, "settings": { "models": "Модели", @@ -543,7 +660,7 @@ "confirmOnDelete": "Подтверждать удаление", "displayHelpIcons": "Показывать значки подсказок", "enableImageDebugging": "Включить отладку", - "resetWebUI": "Сброс настроек Web UI", + "resetWebUI": "Сброс настроек веб-интерфейса", "resetWebUIDesc1": "Сброс настроек веб-интерфейса удаляет только локальный кэш браузера с вашими изображениями и настройками. Он не удаляет изображения с диска.", "resetWebUIDesc2": "Если изображения не отображаются в галерее или не работает что-то еще, пожалуйста, попробуйте сбросить настройки, прежде чем сообщать о проблеме на GitHub.", "resetComplete": "Настройки веб-интерфейса были сброшены.", @@ -563,7 +680,23 @@ "beta": "Бета", "alternateCanvasLayout": "Альтернативный слой холста", "showAdvancedOptions": "Показать доп. параметры", - "autoChangeDimensions": "Обновить Ш/В на стандартные для модели при изменении" + "autoChangeDimensions": "Обновить Ш/В на стандартные для модели при изменении", + "clearIntermediates": "Очистить промежуточные", + "clearIntermediatesDesc3": "Изображения вашей галереи не будут удалены.", + "clearIntermediatesWithCount_one": "Очистить {{count}} промежуточное", + "clearIntermediatesWithCount_few": "Очистить {{count}} промежуточных", + "clearIntermediatesWithCount_many": "Очистить {{count}} промежуточных", + "enableNSFWChecker": "Включить NSFW проверку", + "clearIntermediatesDisabled": "Очередь должна быть пуста, чтобы очистить промежуточные продукты", + "clearIntermediatesDesc2": "Промежуточные изображения — это побочные продукты генерации, отличные от результирующих изображений в галерее. Очистка промежуточных файлов освободит место на диске.", + "enableInvisibleWatermark": "Включить невидимый водяной знак", + "enableInformationalPopovers": "Включить информационные всплывающие окна", + "intermediatesCleared_one": "Очищено {{count}} промежуточное", + "intermediatesCleared_few": "Очищено {{count}} промежуточных", + "intermediatesCleared_many": "Очищено {{count}} промежуточных", + "clearIntermediatesDesc1": "Очистка промежуточных элементов приведет к сбросу состояния Canvas и ControlNet.", + "intermediatesClearedFailed": "Проблема очистки промежуточных", + "reloadingIn": "Перезагрузка через" }, "toast": { "tempFoldersEmptied": "Временная папка очищена", @@ -611,7 +744,48 @@ "nodesNotValidJSON": "Недопустимый JSON", "nodesCorruptedGraph": "Не удается загрузить. Граф, похоже, поврежден.", "nodesSaved": "Узлы сохранены", - "nodesNotValidGraph": "Недопустимый граф узлов InvokeAI" + "nodesNotValidGraph": "Недопустимый граф узлов InvokeAI", + "baseModelChangedCleared_one": "Базовая модель изменила, очистила или отключила {{count}} несовместимую подмодель", + "baseModelChangedCleared_few": "Базовая модель изменила, очистила или отключила {{count}} несовместимые подмодели", + "baseModelChangedCleared_many": "Базовая модель изменила, очистила или отключила {{count}} несовместимых подмоделей", + "imageSavingFailed": "Не удалось сохранить изображение", + "canvasSentControlnetAssets": "Холст отправлен в ControlNet и ресурсы", + "problemCopyingCanvasDesc": "Невозможно экспортировать базовый слой", + "loadedWithWarnings": "Рабочий процесс загружен с предупреждениями", + "setInitialImage": "Установить как исходное изображение", + "canvasCopiedClipboard": "Холст скопирован в буфер обмена", + "setControlImage": "Установить как контрольное изображение", + "setNodeField": "Установить как поле узла", + "problemSavingMask": "Проблема с сохранением маски", + "problemSavingCanvasDesc": "Невозможно экспортировать базовый слой", + "invalidUpload": "Неверная загрузка", + "maskSavedAssets": "Маска сохранена в ресурсах", + "modelAddFailed": "Не удалось добавить модель", + "problemDownloadingCanvas": "Проблема с скачиванием холста", + "setAsCanvasInitialImage": "Установить в качестве исходного изображения холста", + "problemMergingCanvas": "Проблема с объединением холста", + "setCanvasInitialImage": "Установить исходное изображение холста", + "imageUploaded": "Изображение загружено", + "addedToBoard": "Добавлено на доску", + "workflowLoaded": "Рабочий процесс загружен", + "problemDeletingWorkflow": "Проблема с удалением рабочего процесса", + "modelAddedSimple": "Модель добавлена", + "problemImportingMaskDesc": "Невозможно экспортировать маску", + "problemCopyingCanvas": "Проблема с копированием холста", + "workflowDeleted": "Рабочий процесс удален", + "problemSavingCanvas": "Проблема с сохранением холста", + "canvasDownloaded": "Холст скачан", + "setIPAdapterImage": "Установить как образ IP-адаптера", + "problemMergingCanvasDesc": "Невозможно экспортировать базовый слой", + "problemDownloadingCanvasDesc": "Невозможно экспортировать базовый слой", + "problemSavingMaskDesc": "Невозможно экспортировать маску", + "problemRetrievingWorkflow": "Проблема с получением рабочего процесса", + "imageSaved": "Изображение сохранено", + "maskSentControlnetAssets": "Маска отправлена в ControlNet и ресурсы", + "canvasSavedGallery": "Холст сохранен в галерею", + "imageUploadFailed": "Не удалось загрузить изображение", + "modelAdded": "Добавлена модель: {{modelName}}", + "problemImportingMask": "Проблема с импортом маски" }, "tooltip": { "feature": { @@ -686,7 +860,10 @@ "betaDarkenOutside": "Затемнить снаружи", "betaLimitToBox": "Ограничить выделением", "betaPreserveMasked": "Сохранять маскируемую область", - "antialiasing": "Не удалось скопировать ссылку на изображение" + "antialiasing": "Не удалось скопировать ссылку на изображение", + "saveMask": "Сохранить $t(unifiedCanvas.mask)", + "showResultsOn": "Показывать результаты (вкл)", + "showResultsOff": "Показывать результаты (вЫкл)" }, "accessibility": { "modelSelect": "Выбор модели", @@ -708,7 +885,12 @@ "useThisParameter": "Использовать этот параметр", "copyMetadataJson": "Скопировать метаданные JSON", "exitViewer": "Закрыть просмотрщик", - "menu": "Меню" + "menu": "Меню", + "showGalleryPanel": "Показать панель галереи", + "mode": "Режим", + "loadMore": "Загрузить больше", + "resetUI": "$t(accessibility.reset) интерфейс", + "createIssue": "Сообщить о проблеме" }, "ui": { "showProgressImages": "Показывать промежуточный итог", @@ -731,7 +913,212 @@ "resetWorkflow": "Сбросить рабочий процесс", "resetWorkflowDesc": "Вы уверены, что хотите сбросить этот рабочий процесс?", "reloadNodeTemplates": "Перезагрузить шаблоны узлов", - "downloadWorkflow": "Скачать JSON рабочего процесса" + "downloadWorkflow": "Скачать JSON рабочего процесса", + "booleanPolymorphicDescription": "Коллекция логических значений.", + "addNode": "Добавить узел", + "addLinearView": "Добавить в линейный вид", + "animatedEdges": "Анимированные ребра", + "booleanCollectionDescription": "Коллекция логических значений.", + "boardField": "Доска", + "animatedEdgesHelp": "Анимация выбранных ребер и ребер, соединенных с выбранными узлами", + "booleanPolymorphic": "Логическое полиморфное", + "boolean": "Логические значения", + "booleanDescription": "Логические значения могут быть только true или false.", + "cannotConnectInputToInput": "Невозможно подключить вход к входу", + "boardFieldDescription": "Доска галереи", + "cannotConnectOutputToOutput": "Невозможно подключить выход к выходу", + "booleanCollection": "Логическая коллекция", + "addNodeToolTip": "Добавить узел (Shift+A, Пробел)", + "scheduler": "Планировщик", + "inputField": "Поле ввода", + "controlFieldDescription": "Информация об управлении, передаваемая между узлами.", + "skippingUnknownOutputType": "Пропуск неизвестного типа выходного поля", + "denoiseMaskFieldDescription": "Маска шумоподавления может передаваться между узлами", + "floatCollectionDescription": "Коллекция чисел Float.", + "missingTemplate": "Недопустимый узел: узел {{node}} типа {{type}} не имеет шаблона (не установлен?)", + "outputSchemaNotFound": "Схема вывода не найдена", + "ipAdapterPolymorphicDescription": "Коллекция IP-адаптеров.", + "workflowDescription": "Краткое описание", + "inputFieldTypeParseError": "Невозможно разобрать тип поля ввода {{node}}.{{field}} ({{message}})", + "colorFieldDescription": "Цвет RGBA.", + "mainModelField": "Модель", + "unhandledInputProperty": "Необработанное входное свойство", + "unsupportedAnyOfLength": "слишком много элементов объединения ({{count}})", + "versionUnknown": " Версия неизвестна", + "ipAdapterCollection": "Коллекция IP-адаптеров", + "conditioningCollection": "Коллекция условий", + "maybeIncompatible": "Может быть несовместимо с установленным", + "unsupportedArrayItemType": "неподдерживаемый тип элемента массива \"{{type}}\"", + "ipAdapterPolymorphic": "Полиморфный IP-адаптер", + "noNodeSelected": "Узел не выбран", + "unableToValidateWorkflow": "Невозможно проверить рабочий процесс", + "enum": "Перечисления", + "updateAllNodes": "Обновить узлы", + "integerPolymorphicDescription": "Коллекция целых чисел.", + "noOutputRecorded": "Выходы не зарегистрированы", + "updateApp": "Обновить приложение", + "conditioningCollectionDescription": "Условные обозначения могут передаваться между узлами.", + "colorPolymorphic": "Полиморфный цвет", + "colorCodeEdgesHelp": "Цветовая маркировка ребер в соответствии с их связанными полями", + "float": "Float", + "workflowContact": "Контакт", + "targetNodeFieldDoesNotExist": "Неверный край: целевое/вводное поле {{node}}.{{field}} не существует", + "skippingReservedFieldType": "Пропуск зарезервированного типа поля", + "unsupportedMismatchedUnion": "несовпадение типа CollectionOrScalar с базовыми типами {{firstType}} и {{secondType}}", + "sDXLMainModelFieldDescription": "Поле модели SDXL.", + "allNodesUpdated": "Все узлы обновлены", + "conditioningPolymorphic": "Полиморфные условия", + "integer": "Целое число", + "colorField": "Цвет", + "nodeTemplate": "Шаблон узла", + "problemReadingWorkflow": "Проблема с чтением рабочего процесса из изображения", + "sourceNode": "Исходный узел", + "nodeOpacity": "Непрозрачность узла", + "sourceNodeDoesNotExist": "Недопустимое ребро: исходный/выходной узел {{node}} не существует", + "pickOne": "Выбери один", + "integerDescription": "Целые числа — это числа без запятой или точки.", + "outputField": "Поле вывода", + "unableToLoadWorkflow": "Невозможно загрузить рабочий процесс", + "unableToExtractEnumOptions": "невозможно извлечь параметры перечисления", + "snapToGrid": "Привязка к сетке", + "stringPolymorphic": "Полиморфная строка", + "conditioningPolymorphicDescription": "Условие может быть передано между узлами.", + "noFieldsLinearview": "Нет полей, добавленных в линейный вид", + "skipped": "Пропущено", + "unableToParseFieldType": "невозможно проанализировать тип поля", + "imagePolymorphic": "Полиморфное изображение", + "nodeSearch": "Поиск узлов", + "updateNode": "Обновить узел", + "imagePolymorphicDescription": "Коллекция изображений.", + "floatPolymorphic": "Полиморфные Float", + "outputFieldInInput": "Поле вывода во входных данных", + "version": "Версия", + "doesNotExist": "не найдено", + "unrecognizedWorkflowVersion": "Неизвестная версия схемы рабочего процесса {{version}}", + "ipAdapterCollectionDescription": "Коллекция IP-адаптеров.", + "stringCollectionDescription": "Коллекция строк.", + "unableToParseNode": "Невозможно разобрать узел", + "controlCollection": "Контрольная коллекция", + "validateConnections": "Проверка соединений и графика", + "stringCollection": "Коллекция строк", + "inputMayOnlyHaveOneConnection": "Вход может иметь только одно соединение", + "notes": "Заметки", + "outputFieldTypeParseError": "Невозможно разобрать тип поля вывода {{node}}.{{field}} ({{message}})", + "uNetField": "UNet", + "nodeOutputs": "Выходы узла", + "currentImageDescription": "Отображает текущее изображение в редакторе узлов", + "validateConnectionsHelp": "Предотвратить создание недопустимых соединений и вызов недопустимых графиков", + "problemSettingTitle": "Проблема с настройкой названия", + "ipAdapter": "IP-адаптер", + "integerCollection": "Коллекция целых чисел", + "collectionItem": "Элемент коллекции", + "noConnectionInProgress": "Соединение не выполняется", + "vaeModelField": "VAE", + "controlCollectionDescription": "Информация об управлении, передаваемая между узлами.", + "skippedReservedInput": "Пропущено зарезервированное поле ввода", + "workflowVersion": "Версия", + "noConnectionData": "Нет данных о соединении", + "outputFields": "Поля вывода", + "fieldTypesMustMatch": "Типы полей должны совпадать", + "workflow": "Рабочий процесс", + "edge": "Край", + "inputNode": "Входной узел", + "enumDescription": "Перечисления - это значения, которые могут быть одним из нескольких вариантов.", + "unkownInvocation": "Неизвестный тип вызова", + "sourceNodeFieldDoesNotExist": "Неверный край: поле источника/вывода {{node}}.{{field}} не существует", + "imageField": "Изображение", + "skippedReservedOutput": "Пропущено зарезервированное поле вывода", + "cannotDuplicateConnection": "Невозможно создать дубликаты соединений", + "unknownTemplate": "Неизвестный шаблон", + "noWorkflow": "Нет рабочего процесса", + "removeLinearView": "Удалить из линейного вида", + "integerCollectionDescription": "Коллекция целых чисел.", + "colorPolymorphicDescription": "Коллекция цветов.", + "sDXLMainModelField": "Модель SDXL", + "workflowTags": "Теги", + "denoiseMaskField": "Маска шумоподавления", + "missingCanvaInitImage": "Отсутствует начальное изображение холста", + "conditioningFieldDescription": "Условие может быть передано между узлами.", + "clipFieldDescription": "Подмодели Tokenizer и text_encoder.", + "fullyContainNodesHelp": "Чтобы узлы были выбраны, они должны полностью находиться в поле выбора", + "unableToGetWorkflowVersion": "Не удалось получить версию схемы рабочего процесса", + "noImageFoundState": "Начальное изображение не найдено в состоянии", + "workflowValidation": "Ошибка проверки рабочего процесса", + "nodePack": "Пакет узлов", + "stringDescription": "Строки это просто текст.", + "nodeType": "Тип узла", + "noMatchingNodes": "Нет соответствующих узлов", + "fullyContainNodes": "Выбор узлов с полным содержанием", + "integerPolymorphic": "Целочисленные полиморфные", + "executionStateInProgress": "В процессе", + "unableToExtractSchemaNameFromRef": "невозможно извлечь имя схемы из ссылки", + "noFieldType": "Нет типа поля", + "colorCollection": "Коллекция цветов.", + "executionStateError": "Ошибка", + "noOutputSchemaName": "В объекте ref не найдено имя выходной схемы", + "ipAdapterModel": "Модель IP-адаптера", + "prototypeDesc": "Этот вызов является прототипом. Он может претерпевать изменения при обновлении приложения и может быть удален в любой момент.", + "unableToMigrateWorkflow": "Невозможно перенести рабочий процесс", + "skippingInputNoTemplate": "Пропуск поля ввода без шаблона", + "ipAdapterDescription": "Image Prompt Adapter (IP-адаптер).", + "missingCanvaInitMaskImages": "Отсутствуют начальные изображения холста и маски", + "problemReadingMetadata": "Проблема с чтением метаданных с изображения", + "unknownOutput": "Неизвестный вывод: {{name}}", + "stringPolymorphicDescription": "Коллекция строк.", + "oNNXModelField": "Модель ONNX", + "executionStateCompleted": "Выполнено", + "node": "Узел", + "skippingUnknownInputType": "Пропуск неизвестного типа поля", + "workflowAuthor": "Автор", + "currentImage": "Текущее изображение", + "controlField": "Контроль", + "workflowName": "Название", + "collection": "Коллекция", + "ipAdapterModelDescription": "Поле модели IP-адаптера", + "invalidOutputSchema": "Неверная схема вывода", + "unableToUpdateNode": "Невозможно обновить узел", + "floatDescription": "Float - это числа с запятой.", + "floatPolymorphicDescription": "Коллекция Float-ов.", + "vaeField": "VAE", + "conditioningField": "Обусловленность", + "unknownErrorValidatingWorkflow": "Неизвестная ошибка при проверке рабочего процесса", + "collectionFieldType": "Коллекция {{name}}", + "unhandledOutputProperty": "Необработанное выходное свойство", + "workflowNotes": "Примечания", + "string": "Строка", + "floatCollection": "Коллекция Float", + "unknownNodeType": "Неизвестный тип узла", + "unableToUpdateNodes_one": "Невозможно обновить {{count}} узел", + "unableToUpdateNodes_few": "Невозможно обновить {{count}} узла", + "unableToUpdateNodes_many": "Невозможно обновить {{count}} узлов", + "connectionWouldCreateCycle": "Соединение создаст цикл", + "cannotConnectToSelf": "Невозможно подключиться к самому себе", + "notesDescription": "Добавляйте заметки о своем рабочем процессе", + "unknownField": "Неизвестное поле", + "inputFields": "Поля ввода", + "colorCodeEdges": "Ребра с цветовой кодировкой", + "uNetFieldDescription": "Подмодель UNet.", + "unknownNode": "Неизвестный узел", + "targetNodeDoesNotExist": "Недопустимое ребро: целевой/входной узел {{node}} не существует", + "imageCollectionDescription": "Коллекция изображений.", + "mismatchedVersion": "Недопустимый узел: узел {{node}} типа {{type}} имеет несоответствующую версию (попробовать обновить?)", + "unknownFieldType": "$t(nodes.unknownField) тип: {{type}}", + "vaeFieldDescription": "Подмодель VAE.", + "imageFieldDescription": "Изображения могут передаваться между узлами.", + "outputNode": "Выходной узел", + "collectionOrScalarFieldType": "Коллекция | Скаляр {{name}}", + "betaDesc": "Этот вызов находится в бета-версии. Пока он не станет стабильным, в нем могут происходить изменения при обновлении приложений. Мы планируем поддерживать этот вызов в течение длительного времени.", + "nodeVersion": "Версия узла", + "loadingNodes": "Загрузка узлов...", + "snapToGridHelp": "Привязка узлов к сетке при перемещении", + "workflowSettings": "Настройки редактора рабочих процессов", + "sDXLRefinerModelField": "Модель перерисовщик", + "loRAModelField": "LoRA", + "deletedInvalidEdge": "Удалено недопустимое ребро {{source}} -> {{target}}", + "unableToParseEdge": "Невозможно разобрать край", + "unknownInput": "Неизвестный вход: {{name}}", + "oNNXModelFieldDescription": "Поле модели ONNX.", + "imageCollection": "Коллекция изображений" }, "controlnet": { "amult": "a_mult", @@ -755,7 +1142,65 @@ "autoConfigure": "Автонастройка процессора", "delete": "Удалить", "canny": "Canny", - "depthZoeDescription": "Генерация карты глубины с использованием Zoe" + "depthZoeDescription": "Генерация карты глубины с использованием Zoe", + "resize": "Изменить размер", + "showAdvanced": "Показать расширенные", + "addT2IAdapter": "Добавить $t(common.t2iAdapter)", + "importImageFromCanvas": "Импортировать изображение с холста", + "lineartDescription": "Конвертация изображения в контурный рисунок", + "normalBae": "Обычный BAE", + "importMaskFromCanvas": "Импортировать маску с холста", + "hideAdvanced": "Скрыть расширенные", + "controlNetEnabledT2IDisabled": "$t(common.controlNet) включен, $t(common.t2iAdapter)s отключен", + "ipAdapterModel": "Модель адаптера", + "resetControlImage": "Сбросить контрольное изображение", + "prompt": "Запрос", + "controlnet": "$t(controlnet.controlAdapter_one) №{{number}} $t(common.controlNet)", + "openPoseDescription": "Оценка позы человека с помощью Openpose", + "resizeMode": "Режим изменения размера", + "t2iEnabledControlNetDisabled": "$t(common.t2iAdapter) включен, $t(common.controlNet)s отключен", + "weight": "Вес", + "selectModel": "Выберите модель", + "w": "В", + "processor": "Процессор", + "addControlNet": "Добавить $t(common.controlNet)", + "none": "ничего", + "incompatibleBaseModel": "Несовместимая базовая модель:", + "controlNetT2IMutexDesc": "$t(common.controlNet) и $t(common.t2iAdapter) одновременно в настоящее время не поддерживаются.", + "ip_adapter": "$t(controlnet.controlAdapter_one) №{{number}} $t(common.ipAdapter)", + "pidiDescription": "PIDI-обработка изображений", + "mediapipeFace": "Лицо Mediapipe", + "fill": "Заполнить", + "addIPAdapter": "Добавить $t(common.ipAdapter)", + "lineart": "Контурный рисунок", + "colorMapDescription": "Создает карту цветов из изображения", + "lineartAnimeDescription": "Создание контурных рисунков в стиле аниме", + "t2i_adapter": "$t(controlnet.controlAdapter_one) №{{number}} $t(common.t2iAdapter)", + "minConfidence": "Минимальная уверенность", + "imageResolution": "Разрешение изображения", + "colorMap": "Цвет", + "lowThreshold": "Низкий порог", + "highThreshold": "Высокий порог", + "normalBaeDescription": "Обычная обработка BAE", + "noneDescription": "Обработка не применяется", + "saveControlImage": "Сохранить контрольное изображение", + "toggleControlNet": "Переключить эту ControlNet", + "controlAdapter_one": "Адаптер контроля", + "controlAdapter_few": "Адаптера контроля", + "controlAdapter_many": "Адаптеров контроля", + "safe": "Безопасный", + "colorMapTileSize": "Размер плитки", + "lineartAnime": "Контурный рисунок в стиле аниме", + "ipAdapterImageFallback": "Изображение IP Adapter не выбрано", + "mediapipeFaceDescription": "Обнаружение лиц с помощью Mediapipe", + "hedDescription": "Целостное обнаружение границ", + "setControlImageDimensions": "Установите размеры контрольного изображения на Ш/В", + "scribble": "каракули", + "resetIPAdapterImage": "Сбросить изображение IP Adapter", + "handAndFace": "Руки и Лицо", + "enableIPAdapter": "Включить IP Adapter", + "maxFaces": "Макс Лица", + "mlsdDescription": "Минималистичный детектор отрезков линии" }, "boards": { "autoAddBoard": "Авто добавление Доски", @@ -772,6 +1217,440 @@ "uncategorized": "Без категории", "changeBoard": "Изменить Доску", "loading": "Загрузка...", - "clearSearch": "Очистить поиск" + "clearSearch": "Очистить поиск", + "deleteBoardOnly": "Удалить только доску", + "movingImagesToBoard_one": "Перемещаем {{count}} изображение на доску:", + "movingImagesToBoard_few": "Перемещаем {{count}} изображения на доску:", + "movingImagesToBoard_many": "Перемещаем {{count}} изображений на доску:", + "downloadBoard": "Скачать доску", + "deleteBoard": "Удалить доску", + "deleteBoardAndImages": "Удалить доску и изображения", + "deletedBoardsCannotbeRestored": "Удаленные доски не подлежат восстановлению" + }, + "dynamicPrompts": { + "seedBehaviour": { + "perPromptDesc": "Используйте разные сиды для каждого изображения", + "perIterationLabel": "Сид на итерацию", + "perIterationDesc": "Используйте разные сиды для каждой итерации", + "perPromptLabel": "Сид для каждого изображения", + "label": "Поведение сида" + }, + "enableDynamicPrompts": "Динамические запросы", + "combinatorial": "Комбинаторная генерация", + "maxPrompts": "Максимум запросов", + "promptsPreview": "Предпросмотр запросов", + "promptsWithCount_one": "{{count}} Запрос", + "promptsWithCount_few": "{{count}} Запроса", + "promptsWithCount_many": "{{count}} Запросов", + "dynamicPrompts": "Динамические запросы" + }, + "popovers": { + "noiseUseCPU": { + "paragraphs": [ + "Определяет, генерируется ли шум на CPU или на GPU.", + "Если включен шум CPU, определенное начальное число будет создавать одно и то же изображение на любом компьютере.", + "Включение шума CPU не влияет на производительность." + ], + "heading": "Использовать шум CPU" + }, + "paramScheduler": { + "paragraphs": [ + "Планировщик определяет, как итеративно добавлять шум к изображению или как обновлять образец на основе выходных данных модели." + ], + "heading": "Планировщик" + }, + "scaleBeforeProcessing": { + "paragraphs": [ + "Масштабирует выбранную область до размера, наиболее подходящего для модели перед процессом создания изображения." + ], + "heading": "Масштабирование перед обработкой" + }, + "compositingMaskAdjustments": { + "heading": "Регулировка маски", + "paragraphs": [ + "Отрегулируйте маску." + ] + }, + "paramRatio": { + "heading": "Соотношение сторон", + "paragraphs": [ + "Соотношение сторон создаваемого изображения.", + "Размер изображения (в пикселях), эквивалентный 512x512, рекомендуется для моделей SD1.5, а размер, эквивалентный 1024x1024, рекомендуется для моделей SDXL." + ] + }, + "compositingCoherenceSteps": { + "heading": "Шаги", + "paragraphs": [ + null, + "То же, что и основной параметр «Шаги»." + ] + }, + "dynamicPrompts": { + "paragraphs": [ + "Динамические запросы превращают одно приглашение на множество.", + "Базовый синтакиси: \"a {red|green|blue} ball\". В итоге будет 3 запроса: \"a red ball\", \"a green ball\" и \"a blue ball\".", + "Вы можете использовать синтаксис столько раз, сколько захотите в одном запросе, но обязательно контролируйте количество генерируемых запросов с помощью параметра «Максимальное количество запросов»." + ], + "heading": "Динамические запросы" + }, + "paramVAE": { + "paragraphs": [ + "Модель, используемая для преобразования вывода AI в конечное изображение." + ], + "heading": "VAE" + }, + "compositingBlur": { + "heading": "Размытие", + "paragraphs": [ + "Радиус размытия маски." + ] + }, + "paramIterations": { + "paragraphs": [ + "Количество изображений, которые нужно сгенерировать.", + "Если динамические подсказки включены, каждое из подсказок будет генерироваться столько раз." + ], + "heading": "Итерации" + }, + "paramVAEPrecision": { + "heading": "Точность VAE", + "paragraphs": [ + "Точность, используемая во время кодирования и декодирования VAE. Точность FP16/половина более эффективна за счет незначительных изменений изображения." + ] + }, + "compositingCoherenceMode": { + "heading": "Режим" + }, + "paramSeed": { + "paragraphs": [ + "Управляет стартовым шумом, используемым для генерации.", + "Отключите «Случайное начальное число», чтобы получить идентичные результаты с теми же настройками генерации." + ], + "heading": "Сид" + }, + "controlNetResizeMode": { + "heading": "Режим изменения размера", + "paragraphs": [ + "Как изображение ControlNet будет соответствовать размеру выходного изображения." + ] + }, + "controlNetBeginEnd": { + "paragraphs": [ + "На каких этапах процесса шумоподавления будет применена ControlNet.", + "ControlNet, применяемые в начале процесса, направляют композицию, а ControlNet, применяемые в конце, направляют детали." + ], + "heading": "Процент начала/конца шага" + }, + "dynamicPromptsSeedBehaviour": { + "paragraphs": [ + "Управляет использованием сида при создании запросов.", + "Для каждой итерации будет использоваться уникальный сид. Используйте это, чтобы изучить варианты запросов для одного сида.", + "Например, если у вас 5 запросов, каждое изображение будет использовать один и то же сид.", + "для каждого изображения будет использоваться уникальный сид. Это обеспечивает большую вариативность." + ], + "heading": "Поведение сида" + }, + "clipSkip": { + "paragraphs": [ + "Выберите, сколько слоев модели CLIP нужно пропустить.", + "Некоторые модели работают лучше с определенными настройками пропуска CLIP.", + "Более высокое значение обычно приводит к менее детализированному изображению." + ], + "heading": "CLIP пропуск" + }, + "paramModel": { + "heading": "Модель", + "paragraphs": [ + "Модель, используемая для шагов шумоподавления.", + "Различные модели обычно обучаются, чтобы специализироваться на достижении определенных эстетических результатов и содержания." + ] + }, + "compositingCoherencePass": { + "heading": "Согласованность", + "paragraphs": [ + "Второй этап шумоподавления помогает исправить шов между изначальным изображением и перерисованной или расширенной частью." + ] + }, + "paramDenoisingStrength": { + "paragraphs": [ + "Количество шума, добавляемого к входному изображению.", + "0 приведет к идентичному изображению, а 1 - к совершенно новому." + ], + "heading": "Шумоподавление" + }, + "compositingStrength": { + "heading": "Сила", + "paragraphs": [ + null, + "То же, что параметр «Сила шумоподавления img2img»." + ] + }, + "paramNegativeConditioning": { + "paragraphs": [ + "Stable Diffusion пытается избежать указанных в отрицательном запросе концепций. Используйте это, чтобы исключить качества или объекты из вывода.", + "Поддерживает синтаксис Compel и встраивания." + ], + "heading": "Негативный запрос" + }, + "compositingBlurMethod": { + "heading": "Метод размытия", + "paragraphs": [ + "Метод размытия, примененный к замаскированной области." + ] + }, + "dynamicPromptsMaxPrompts": { + "heading": "Макс. запросы", + "paragraphs": [ + "Ограничивает количество запросов, которые могут быть созданы с помощью динамических запросов." + ] + }, + "paramCFGRescaleMultiplier": { + "heading": "Множитель масштабирования CFG", + "paragraphs": [ + "Множитель масштабирования CFG, используемый для моделей, обученных с использованием нулевого терминального SNR (ztsnr). Рекомендуемое значение 0,7." + ] + }, + "infillMethod": { + "paragraphs": [ + "Метод заполнения выбранной области." + ], + "heading": "Метод заполнения" + }, + "controlNetWeight": { + "heading": "Вес", + "paragraphs": [ + "Насколько сильно ControlNet повлияет на созданное изображение." + ] + }, + "controlNet": { + "heading": "ControlNet", + "paragraphs": [ + "Сети ControlNets обеспечивают руководство процессом генерации, помогая создавать изображения с контролируемой композицией, структурой или стилем, в зависимости от выбранной модели." + ] + }, + "paramCFGScale": { + "heading": "Шкала точности (CFG)", + "paragraphs": [ + "Контролирует, насколько ваш запрос влияет на процесс генерации." + ] + }, + "controlNetControlMode": { + "paragraphs": [ + "Придает больший вес либо запросу, либо ControlNet." + ], + "heading": "Режим управления" + }, + "paramSteps": { + "heading": "Шаги", + "paragraphs": [ + "Количество шагов, которые будут выполнены в ходе генерации.", + "Большее количество шагов обычно приводит к созданию более качественных изображений, но требует больше времени на создание." + ] + }, + "paramPositiveConditioning": { + "heading": "Запрос", + "paragraphs": [ + "Направляет процесс генерации. Вы можете использовать любые слова и фразы.", + "Большинство моделей Stable Diffusion работают только с запросом на английском языке, но бывают исключения." + ] + }, + "lora": { + "heading": "Вес LoRA", + "paragraphs": [ + "Более высокий вес LoRA приведет к большему влиянию на конечное изображение." + ] + } + }, + "metadata": { + "seamless": "Бесшовность", + "positivePrompt": "Запрос", + "negativePrompt": "Негативный запрос", + "generationMode": "Режим генерации", + "Threshold": "Шумовой порог", + "metadata": "Метаданные", + "strength": "Сила img2img", + "seed": "Сид", + "imageDetails": "Детали изображения", + "perlin": "Шум Перлига", + "model": "Модель", + "noImageDetails": "Детали изображения не найдены", + "hiresFix": "Оптимизация высокого разрешения", + "cfgScale": "Шкала точности", + "fit": "Соответствие изображения к изображению", + "initImage": "Исходное изображение", + "recallParameters": "Вызов параметров", + "height": "Высота", + "variations": "Пары сид-высота", + "noMetaData": "Метаданные не найдены", + "width": "Ширина", + "vae": "VAE", + "createdBy": "Сделано", + "workflow": "Рабочий процесс", + "steps": "Шаги", + "scheduler": "Планировщик", + "noRecallParameters": "Параметры для вызова не найдены", + "cfgRescaleMultiplier": "$t(parameters.cfgRescaleMultiplier)" + }, + "queue": { + "status": "Статус", + "pruneSucceeded": "Из очереди удалено {{item_count}} выполненных элементов", + "cancelTooltip": "Отменить текущий элемент", + "queueEmpty": "Очередь пуста", + "pauseSucceeded": "Рендеринг приостановлен", + "in_progress": "В процессе", + "queueFront": "Добавить в начало очереди", + "notReady": "Невозможно поставить в очередь", + "batchFailedToQueue": "Не удалось поставить пакет в очередь", + "completed": "Выполнено", + "queueBack": "Добавить в очередь", + "batchValues": "Пакетные значения", + "cancelFailed": "Проблема с отменой элемента", + "queueCountPrediction": "Добавить {{predicted}} в очередь", + "batchQueued": "Пакетная очередь", + "pauseFailed": "Проблема с приостановкой рендеринга", + "clearFailed": "Проблема с очисткой очереди", + "queuedCount": "{{pending}} Ожидание", + "front": "передний", + "clearSucceeded": "Очередь очищена", + "pause": "Пауза", + "pruneTooltip": "Удалить {{item_count}} выполненных задач", + "cancelSucceeded": "Элемент отменен", + "batchQueuedDesc_one": "Добавлен {{count}} сеанс в {{direction}} очереди", + "batchQueuedDesc_few": "Добавлено {{count}} сеанса в {{direction}} очереди", + "batchQueuedDesc_many": "Добавлено {{count}} сеансов в {{direction}} очереди", + "graphQueued": "График поставлен в очередь", + "queue": "Очередь", + "batch": "Пакет", + "clearQueueAlertDialog": "Очистка очереди немедленно отменяет все элементы обработки и полностью очищает очередь.", + "pending": "В ожидании", + "completedIn": "Завершено за", + "resumeFailed": "Проблема с возобновлением рендеринга", + "clear": "Очистить", + "prune": "Сократить", + "total": "Всего", + "canceled": "Отменено", + "pruneFailed": "Проблема с сокращением очереди", + "cancelBatchSucceeded": "Пакет отменен", + "clearTooltip": "Отменить все и очистить очередь", + "current": "Текущий", + "pauseTooltip": "Приостановить рендеринг", + "failed": "Неудачно", + "cancelItem": "Отменить элемент", + "next": "Следующий", + "cancelBatch": "Отменить пакет", + "back": "задний", + "batchFieldValues": "Пакетные значения полей", + "cancel": "Отмена", + "session": "Сессия", + "time": "Время", + "queueTotal": "{{total}} Всего", + "resumeSucceeded": "Рендеринг возобновлен", + "enqueueing": "Пакетная очередь", + "resumeTooltip": "Возобновить рендеринг", + "queueMaxExceeded": "Превышено максимальное значение {{max_queue_size}}, будет пропущен {{skip}}", + "resume": "Продолжить", + "cancelBatchFailed": "Проблема с отменой пакета", + "clearQueueAlertDialog2": "Вы уверены, что хотите очистить очередь?", + "item": "Элемент", + "graphFailedToQueue": "Не удалось поставить график в очередь" + }, + "sdxl": { + "refinerStart": "Запуск перерисовщика", + "selectAModel": "Выберите модель", + "scheduler": "Планировщик", + "cfgScale": "Шкала точности (CFG)", + "negStylePrompt": "Негативный запрос стиля", + "noModelsAvailable": "Нет доступных моделей", + "refiner": "Перерисовщик", + "negAestheticScore": "Отрицательная эстетическая оценка", + "useRefiner": "Использовать перерисовщик", + "denoisingStrength": "Шумоподавление", + "refinermodel": "Модель перерисовщик", + "posAestheticScore": "Положительная эстетическая оценка", + "concatPromptStyle": "Объединение запроса и стиля", + "loading": "Загрузка...", + "steps": "Шаги", + "posStylePrompt": "Запрос стиля" + }, + "invocationCache": { + "useCache": "Использовать кэш", + "disable": "Отключить", + "misses": "Промахи в кэше", + "enableFailed": "Проблема с включением кэша вызовов", + "invocationCache": "Кэш вызовов", + "clearSucceeded": "Кэш вызовов очищен", + "enableSucceeded": "Кэш вызовов включен", + "clearFailed": "Проблема с очисткой кэша вызовов", + "hits": "Попадания в кэш", + "disableSucceeded": "Кэш вызовов отключен", + "disableFailed": "Проблема с отключением кэша вызовов", + "enable": "Включить", + "clear": "Очистить", + "maxCacheSize": "Максимальный размер кэша", + "cacheSize": "Размер кэша" + }, + "workflows": { + "saveWorkflowAs": "Сохранить рабочий процесс как", + "workflowEditorMenu": "Меню редактора рабочего процесса", + "noSystemWorkflows": "Нет системных рабочих процессов", + "workflowName": "Имя рабочего процесса", + "noUserWorkflows": "Нет пользовательских рабочих процессов", + "defaultWorkflows": "Рабочие процессы по умолчанию", + "saveWorkflow": "Сохранить рабочий процесс", + "openWorkflow": "Открытый рабочий процесс", + "clearWorkflowSearchFilter": "Очистить фильтр поиска рабочих процессов", + "workflowEditorReset": "Сброс редактора рабочих процессов", + "workflowLibrary": "Библиотека", + "downloadWorkflow": "Скачать рабочий процесс", + "noRecentWorkflows": "Нет недавних рабочих процессов", + "workflowSaved": "Рабочий процесс сохранен", + "workflowIsOpen": "Рабочий процесс открыт", + "unnamedWorkflow": "Безымянный рабочий процесс", + "savingWorkflow": "Сохранение рабочего процесса...", + "problemLoading": "Проблема с загрузкой рабочих процессов", + "loading": "Загрузка рабочих процессов", + "searchWorkflows": "Поиск рабочих процессов", + "problemSavingWorkflow": "Проблема с сохранением рабочего процесса", + "deleteWorkflow": "Удалить рабочий процесс", + "workflows": "Рабочие процессы", + "noDescription": "Без описания", + "uploadWorkflow": "Загрузить рабочий процесс", + "userWorkflows": "Мои рабочие процессы" + }, + "embedding": { + "noEmbeddingsLoaded": "встраивания не загружены", + "noMatchingEmbedding": "Нет подходящих встраиваний", + "addEmbedding": "Добавить встраивание", + "incompatibleModel": "Несовместимая базовая модель:" + }, + "hrf": { + "enableHrf": "Включить исправление высокого разрешения", + "upscaleMethod": "Метод увеличения", + "enableHrfTooltip": "Сгенерируйте с более низким начальным разрешением, увеличьте его до базового разрешения, а затем запустите Image-to-Image.", + "metadata": { + "strength": "Сила исправления высокого разрешения", + "enabled": "Исправление высокого разрешения включено", + "method": "Метод исправления высокого разрешения" + }, + "hrf": "Исправление высокого разрешения", + "hrfStrength": "Сила исправления высокого разрешения", + "strengthTooltip": "Более низкие значения приводят к меньшему количеству деталей, что может уменьшить потенциальные артефакты." + }, + "models": { + "noLoRAsLoaded": "LoRA не загружены", + "noMatchingModels": "Нет подходящих моделей", + "esrganModel": "Модель ESRGAN", + "loading": "загрузка", + "noMatchingLoRAs": "Нет подходящих LoRA", + "noLoRAsAvailable": "Нет доступных LoRA", + "noModelsAvailable": "Нет доступных моделей", + "addLora": "Добавить LoRA", + "selectModel": "Выберите модель", + "noRefinerModelsInstalled": "Модели SDXL Refiner не установлены", + "noLoRAsInstalled": "Нет установленных LoRA", + "selectLoRA": "Выберите LoRA" + }, + "app": { + "storeNotInitialized": "Магазин не инициализирован" } } diff --git a/invokeai/frontend/web/public/locales/zh_CN.json b/invokeai/frontend/web/public/locales/zh_CN.json index b1b6852f25..b29cf037d3 100644 --- a/invokeai/frontend/web/public/locales/zh_CN.json +++ b/invokeai/frontend/web/public/locales/zh_CN.json @@ -110,7 +110,17 @@ "copyError": "$t(gallery.copy) 错误", "input": "输入", "notInstalled": "非 $t(common.installed)", - "delete": "删除" + "delete": "删除", + "updated": "已上传", + "save": "保存", + "created": "已创建", + "prevPage": "上一页", + "unknownError": "未知错误", + "direction": "指向", + "orderBy": "排序方式:", + "nextPage": "下一页", + "saveAs": "保存为", + "unsaved": "未保存" }, "gallery": { "generations": "生成的图像", @@ -146,7 +156,11 @@ "image": "图像", "drop": "弃用", "dropOrUpload": "$t(gallery.drop) 或上传", - "dropToUpload": "$t(gallery.drop) 以上传" + "dropToUpload": "$t(gallery.drop) 以上传", + "problemDeletingImagesDesc": "有一张或多张图像无法被删除", + "problemDeletingImages": "删除图像时出现问题", + "unstarImage": "取消收藏图像", + "starImage": "收藏图像" }, "hotkeys": { "keyboardShortcuts": "键盘快捷键", @@ -724,7 +738,7 @@ "nodesUnrecognizedTypes": "无法加载。节点图有无法识别的节点类型", "nodesNotValidJSON": "无效的 JSON", "nodesNotValidGraph": "无效的 InvokeAi 节点图", - "nodesLoadedFailed": "节点图加载失败", + "nodesLoadedFailed": "节点加载失败", "modelAddedSimple": "已添加模型", "modelAdded": "已添加模型: {{modelName}}", "imageSavingFailed": "图像保存失败", @@ -760,7 +774,10 @@ "problemImportingMask": "导入遮罩时出现问题", "baseModelChangedCleared_other": "基础模型已更改, 已清除或禁用 {{count}} 个不兼容的子模型", "setAsCanvasInitialImage": "设为画布初始图像", - "invalidUpload": "无效的上传" + "invalidUpload": "无效的上传", + "problemDeletingWorkflow": "删除工作流时出现问题", + "workflowDeleted": "已删除工作流", + "problemRetrievingWorkflow": "检索工作流时发生问题" }, "unifiedCanvas": { "layer": "图层", @@ -875,11 +892,11 @@ }, "nodes": { "zoomInNodes": "放大", - "resetWorkflowDesc": "是否确定要清空节点图?", - "resetWorkflow": "清空节点图", - "loadWorkflow": "读取节点图", + "resetWorkflowDesc": "是否确定要重置工作流编辑器?", + "resetWorkflow": "重置工作流编辑器", + "loadWorkflow": "加载工作流", "zoomOutNodes": "缩小", - "resetWorkflowDesc2": "重置节点图将清除所有节点、边际和节点图详情.", + "resetWorkflowDesc2": "重置工作流编辑器将清除所有节点、边际和节点图详情。不影响已保存的工作流。", "reloadNodeTemplates": "重载节点模板", "hideGraphNodes": "隐藏节点图信息", "fitViewportNodes": "自适应视图", @@ -888,7 +905,7 @@ "showLegendNodes": "显示字段类型图例", "hideLegendNodes": "隐藏字段类型图例", "showGraphNodes": "显示节点图信息", - "downloadWorkflow": "下载节点图 JSON", + "downloadWorkflow": "下载工作流 JSON", "workflowDescription": "简述", "versionUnknown": " 未知版本", "noNodeSelected": "无选中的节点", @@ -1103,7 +1120,9 @@ "collectionOrScalarFieldType": "{{name}} 合集 | 标量", "nodeVersion": "节点版本", "deletedInvalidEdge": "已删除无效的边缘 {{source}} -> {{target}}", - "unknownInput": "未知输入:{{name}}" + "unknownInput": "未知输入:{{name}}", + "prototypeDesc": "此调用是一个原型 (prototype)。它可能会在本项目更新期间发生破坏性更改,并且随时可能被删除。", + "betaDesc": "此调用尚处于测试阶段。在稳定之前,它可能会在项目更新期间发生破坏性更改。本项目计划长期支持这种调用。" }, "controlnet": { "resize": "直接缩放", @@ -1607,5 +1626,36 @@ "hrf": "高分辨率修复", "hrfStrength": "高分辨率修复强度", "strengthTooltip": "值越低细节越少,但可以减少部分潜在的伪影。" + }, + "workflows": { + "saveWorkflowAs": "保存工作流为", + "workflowEditorMenu": "工作流编辑器菜单", + "noSystemWorkflows": "无系统工作流", + "workflowName": "工作流名称", + "noUserWorkflows": "无用户工作流", + "defaultWorkflows": "默认工作流", + "saveWorkflow": "保存工作流", + "openWorkflow": "打开工作流", + "clearWorkflowSearchFilter": "清除工作流检索过滤器", + "workflowEditorReset": "工作流编辑器重置", + "workflowLibrary": "工作流库", + "downloadWorkflow": "下载工作流", + "noRecentWorkflows": "无最近工作流", + "workflowSaved": "已保存工作流", + "workflowIsOpen": "工作流已打开", + "unnamedWorkflow": "未命名的工作流", + "savingWorkflow": "保存工作流中...", + "problemLoading": "加载工作流时出现问题", + "loading": "加载工作流中", + "searchWorkflows": "检索工作流", + "problemSavingWorkflow": "保存工作流时出现问题", + "deleteWorkflow": "删除工作流", + "workflows": "工作流", + "noDescription": "无描述", + "uploadWorkflow": "上传工作流", + "userWorkflows": "我的工作流" + }, + "app": { + "storeNotInitialized": "商店尚未初始化" } } diff --git a/invokeai/frontend/web/src/features/nodes/util/workflow/migrations.ts b/invokeai/frontend/web/src/features/nodes/util/workflow/migrations.ts index fddd4de495..a8212f06b6 100644 --- a/invokeai/frontend/web/src/features/nodes/util/workflow/migrations.ts +++ b/invokeai/frontend/web/src/features/nodes/util/workflow/migrations.ts @@ -64,7 +64,10 @@ const migrateV1toV2 = (workflowToMigrate: WorkflowV1): WorkflowV2 => { const nodePack = invocationTemplate ? invocationTemplate.nodePack : t('common.unknown'); + (node.data as unknown as InvocationNodeData).nodePack = nodePack; + // Fallback to 1.0.0 if not specified - this matches the behavior of the backend + node.data.version ||= '1.0.0'; } }); // Bump version diff --git a/invokeai/frontend/web/src/features/workflowLibrary/components/WorkflowLibraryMenu/ResetWorkflowEditorMenuItem.tsx b/invokeai/frontend/web/src/features/workflowLibrary/components/WorkflowLibraryMenu/NewWorkflowMenuItem.tsx similarity index 63% rename from invokeai/frontend/web/src/features/workflowLibrary/components/WorkflowLibraryMenu/ResetWorkflowEditorMenuItem.tsx rename to invokeai/frontend/web/src/features/workflowLibrary/components/WorkflowLibraryMenu/NewWorkflowMenuItem.tsx index 5d7e58e198..c4497c5ddb 100644 --- a/invokeai/frontend/web/src/features/workflowLibrary/components/WorkflowLibraryMenu/ResetWorkflowEditorMenuItem.tsx +++ b/invokeai/frontend/web/src/features/workflowLibrary/components/WorkflowLibraryMenu/NewWorkflowMenuItem.tsx @@ -11,44 +11,48 @@ import { Text, useDisclosure, } from '@chakra-ui/react'; -import { useAppDispatch } from 'app/store/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { nodeEditorReset } from 'features/nodes/store/nodesSlice'; import { addToast } from 'features/system/store/systemSlice'; import { makeToast } from 'features/system/util/makeToast'; import { memo, useCallback, useRef } from 'react'; import { useTranslation } from 'react-i18next'; -import { FaTrash } from 'react-icons/fa'; +import { FaCircleNodes } from 'react-icons/fa6'; -const ResetWorkflowEditorMenuItem = () => { +const NewWorkflowMenuItem = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); const { isOpen, onOpen, onClose } = useDisclosure(); const cancelRef = useRef(null); + const isTouched = useAppSelector((state) => state.workflow.isTouched); - const handleConfirmClear = useCallback(() => { + const handleNewWorkflow = useCallback(() => { dispatch(nodeEditorReset()); dispatch( addToast( makeToast({ - title: t('workflows.workflowEditorReset'), + title: t('workflows.newWorkflowCreated'), status: 'success', }) ) ); onClose(); - }, [dispatch, t, onClose]); + }, [dispatch, onClose, t]); + + const onClick = useCallback(() => { + if (!isTouched) { + handleNewWorkflow(); + return; + } + onOpen(); + }, [handleNewWorkflow, isTouched, onOpen]); return ( <> - } - sx={{ color: 'error.600', _dark: { color: 'error.300' } }} - onClick={onOpen} - > - {t('nodes.resetWorkflow')} + } onClick={onClick}> + {t('nodes.newWorkflow')} { - {t('nodes.resetWorkflow')} + {t('nodes.newWorkflow')} - {t('nodes.resetWorkflowDesc')} - {t('nodes.resetWorkflowDesc2')} + {t('nodes.newWorkflowDesc')} + {t('nodes.newWorkflowDesc2')} @@ -75,7 +79,7 @@ const ResetWorkflowEditorMenuItem = () => { - @@ -85,4 +89,4 @@ const ResetWorkflowEditorMenuItem = () => { ); }; -export default memo(ResetWorkflowEditorMenuItem); +export default memo(NewWorkflowMenuItem); diff --git a/invokeai/frontend/web/src/features/workflowLibrary/components/WorkflowLibraryMenu/WorkflowLibraryMenu.tsx b/invokeai/frontend/web/src/features/workflowLibrary/components/WorkflowLibraryMenu/WorkflowLibraryMenu.tsx index a19b9cd6b5..c07bb8f5cd 100644 --- a/invokeai/frontend/web/src/features/workflowLibrary/components/WorkflowLibraryMenu/WorkflowLibraryMenu.tsx +++ b/invokeai/frontend/web/src/features/workflowLibrary/components/WorkflowLibraryMenu/WorkflowLibraryMenu.tsx @@ -9,7 +9,7 @@ import IAIIconButton from 'common/components/IAIIconButton'; import { useGlobalMenuCloseTrigger } from 'common/hooks/useGlobalMenuCloseTrigger'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import DownloadWorkflowMenuItem from 'features/workflowLibrary/components/WorkflowLibraryMenu/DownloadWorkflowMenuItem'; -import ResetWorkflowEditorMenuItem from 'features/workflowLibrary/components/WorkflowLibraryMenu/ResetWorkflowEditorMenuItem'; +import NewWorkflowMenuItem from 'features/workflowLibrary/components/WorkflowLibraryMenu/NewWorkflowMenuItem'; import SaveWorkflowAsMenuItem from 'features/workflowLibrary/components/WorkflowLibraryMenu/SaveWorkflowAsMenuItem'; import SaveWorkflowMenuItem from 'features/workflowLibrary/components/WorkflowLibraryMenu/SaveWorkflowMenuItem'; import SettingsMenuItem from 'features/workflowLibrary/components/WorkflowLibraryMenu/SettingsMenuItem'; @@ -39,7 +39,7 @@ const WorkflowLibraryMenu = () => { {isWorkflowLibraryEnabled && } - + diff --git a/mkdocs.yml b/mkdocs.yml index d030e3d6fc..7c67a2777a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -101,6 +101,8 @@ plugins: extra_javascript: - https://unpkg.com/tablesort@5.3.0/dist/tablesort.min.js - javascripts/tablesort.js + - https://widget.kapa.ai/kapa-widget.bundle.js + - javascript/init_kapa_widget.js extra: analytics: