init i18n extension

This commit is contained in:
xbol0 2023-08-08 07:50:57 +00:00
parent 0ce8a540ce
commit 2542a6bf93
12 changed files with 3109 additions and 108 deletions

1
.gitignore vendored
View File

@ -14,3 +14,4 @@ venv/
web/extensions/*
!web/extensions/logging.js.example
!web/extensions/core/
!web/extensions/i18n/

View File

@ -435,7 +435,7 @@ app.registerExtension({
$el("td", [
$el("label", {
for: id.replaceAll(".", "-"),
textContent: "Color palette",
textContent: i18next.t("settings.Comfy.ColorPalette"),
}),
]),
$el("td", [
@ -449,7 +449,7 @@ app.registerExtension({
}, [
$el("input", {
type: "button",
value: "Export",
value: i18next.t("settings.Comfy.ColorPalette.export"),
onclick: async () => {
const colorPaletteId = app.ui.settings.getSettingValue(id, defaultColorPaletteId);
const colorPalette = await completeColorPalette(getColorPalette(colorPaletteId));
@ -471,14 +471,14 @@ app.registerExtension({
}),
$el("input", {
type: "button",
value: "Import",
value: i18next.t("settings.Comfy.ColorPalette.import"),
onclick: () => {
fileInput.click();
}
}),
$el("input", {
type: "button",
value: "Template",
value: i18next.t("settings.Comfy.ColorPalette.template"),
onclick: async () => {
const colorPalette = await getColorPaletteTemplate();
const json = JSON.stringify(colorPalette, null, 2); // convert the data to a JSON string
@ -499,7 +499,7 @@ app.registerExtension({
}),
$el("input", {
type: "button",
value: "Delete",
value: i18next.t("settings.Comfy.ColorPalette.delete"),
onclick: async () => {
let colorPaletteId = app.ui.settings.getSettingValue(id, defaultColorPaletteId);

View File

@ -0,0 +1,46 @@
import { app } from "../../scripts/app.js";
app.registerExtension({
name: "i18next",
addCustomNodeDefs(defs) {
for (const k in defs) {
defs[k].display_name = i18next.t(`node.title.${k}`)
if ("input" in defs[k] && defs[k].input.required) {
for (const i in defs[k].input.required) {
if (defs[k].input.required[i].length > 1) {
defs[k].input.required[i][1].label = i18next.t(`node.input.${k}.${i}`)
} else {
defs[k].input.required[i].push({ label: i18next.t(`node.input.${k}.${i}`) })
}
}
}
}
},
nodeCreated(node) {
if ("inputs" in node) {
for (const item of node.inputs) {
item.label = i18next.t(`node.input.${node.comfyClass}.${item.name}`)
}
}
if ("widgets" in node) {
for (const item of node.widgets) {
item.label = i18next.t(`node.input.${node.comfyClass}.${item.name}`)
}
}
if ("outputs" in node) {
for (const item of node.outputs) {
item.label = i18next.t(`node.output.${node.comfyClass}.${item.name}`)
}
}
},
afterNodesRegistrations() {
const defs = LiteGraph.registered_node_types
for (const k in defs) {
defs[k].category = i18next.t(`category.${defs[k].category}`)
}
}
})

View File

@ -57,6 +57,7 @@ function convertToInput(node, widget, config) {
const sz = node.size;
node.addInput(widget.name, linkType, {
widget: { name: widget.name, config },
label: config?.[1] ? i18next.t(config?.[1].label) : void 0,
});
for (const widget of node.widgets) {

125
web/i18n/en_US.js Normal file
View File

@ -0,0 +1,125 @@
export default {
translation: {
"ui.queue_btn": "Queue Prompt",
"ui.queue_front_btn": "Queue Front",
"ui.view_queue_btn": "View Queue",
"ui.view_history_btn": "View History",
"ui.save_btn": "Save",
"ui.load_btn": "Load",
"ui.refresh_btn": "Refresh",
"ui.clipspace_btn": "Clipspace",
"ui.clear_btn": "Clear",
"ui.load_default_btn": "Load Default",
"ui.close_btn": "Close",
"ui.queue_size": "Queue size: ",
"ui.extra_options": "Extra options",
"ui.settings.title": "Settings",
"ui.canvas_menu_add_node": "Add Node",
"ui.canvas_menu_add_group": "Add Group",
"ui.node_panel.header.properties": "Properties",
"ui.node_panel.header.title": "Title",
"ui.node_panel.header.mode": "Mode",
"ui.node_panel.header.color": "Color",
"node.title.KSampler": "KSampler",
"node.title.KSamplerAdvanced": "KSampler (Advanced)",
// Loaders
"node.title.CheckpointLoader": "Load Checkpoint (With Config)",
"node.title.CheckpointLoaderSimple": "Load Checkpoint",
"node.title.VAELoader": "Load VAE",
"node.title.LoraLoader": "Load LoRA",
"node.title.CLIPLoader": "Load CLIP",
"node.title.ControlNetLoader": "Load ControlNet Model",
"node.title.DiffControlNetLoader": "Load ControlNet Model (diff)",
"node.title.StyleModelLoader": "Load Style Model",
"node.title.CLIPVisionLoader": "Load CLIP Vision",
"node.title.UpscaleModelLoader": "Load Upscale Model",
// Conditioning
"node.title.CLIPVisionEncode": "CLIP Vision Encode",
"node.title.StyleModelApply": "Apply Style Model",
"node.title.CLIPTextEncode": "CLIP Text Encode (Prompt)",
"node.title.CLIPSetLastLayer": "CLIP Set Last Layer",
"node.title.ConditioningCombine": "Conditioning (Combine)",
"node.title.ConditioningAverage ": "Conditioning (Average)",
"node.title.ConditioningConcat": "Conditioning (Concat)",
"node.title.ConditioningSetArea": "Conditioning (Set Area)",
"node.title.ConditioningSetMask": "Conditioning (Set Mask)",
"node.title.ControlNetApply": "Apply ControlNet",
"node.title.ControlNetApplyAdvanced": "Apply ControlNet (Advanced)",
// Latent
"node.title.VAEEncodeForInpaint": "VAE Encode (for Inpainting)",
"node.title.SetLatentNoiseMask": "Set Latent Noise Mask",
"node.title.VAEDecode": "VAE Decode",
"node.title.VAEEncode": "VAE Encode",
"node.title.LatentRotate": "Rotate Latent",
"node.title.LatentFlip": "Flip Latent",
"node.title.LatentCrop": "Crop Latent",
"node.title.EmptyLatentImage": "Empty Latent Image",
"node.title.LatentUpscale": "Upscale Latent",
"node.title.LatentUpscaleBy": "Upscale Latent By",
"node.title.LatentComposite": "Latent Composite",
"node.title.LatentBlend": "Latent Blend",
"LatentFromBatch": "Latent From Batch",
"node.title.RepeatLatentBatch": "Repeat Latent Batch",
// Image
"node.title.SaveImage": "Save Image",
"node.title.PreviewImage": "Preview Image",
"node.title.LoadImage": "Load Image",
"node.title.LoadImageMask": "Load Image (as Mask)",
"node.title.ImageScale": "Upscale Image",
"node.title.ImageScaleBy": "Upscale Image By",
"node.title.ImageUpscaleWithModel": "Upscale Image (using Model)",
"node.title.ImageInvert": "Invert Image",
"node.title.ImagePadForOutpaint": "Pad Image for Outpainting",
// _for_testing
"node.title.VAEDecodeTiled": "VAE Decode (Tiled)",
"node.title.VAEEncodeTiled": "VAE Encode (Tiled)",
"node.input.SaveImage.filename_prefix": "filename_prefix",
"node.input.SaveImage.images": "images",
"node.output.CheckpointLoaderSimple.MODEL": "MODEL",
"category.conditioning": "conditioning",
"category.loaders": "loaders",
"category.latent": "latent",
"category.latent/inpaint": "latent/inpaint",
"category.latent/batch": "latent/batch",
"category.image": "image",
"category.mask": "mask",
"category.image/upscaling": "image/upscaling",
"category.sampling": "sampling",
"category._for_testing": "_for_testing",
"category.latent/transform": "latent/transform",
"category.advanced/loaders": "advanced/loaders",
"category.conditioning/style_model": "conditioning/style_model",
"category.conditioning/gligen": "conditioning/gligen",
"category.advanced/loaders/deprecated": "advanced/loaders/deprecated",
"category.advanced/conditioning": "advanced/conditioning",
"category.image/postprocessing": "image/postprocessing",
"category.advanced/model_merging": "advanced/model_merging",
"category.image/preprocessors": "image/preprocessors",
"category.utils": "utils",
"settings.Comfy.ConfirmClear": "Require confirmation when clearing workflow",
"settings.Comfy.PromptFilename": "Prompt for filename when saving workflow",
"settings.Comfy.PreviewFormat": "When displaying a preview in the image widget, convert it to a lightweight image, e.g. webp, jpeg, webp;50, etc.",
"settings.Comfy.DisableSliders": "Disable sliders.",
"settings.Comfy.DevMode": "Enable Dev mode Options",
"settings.Comfy.ColorPalette": "Color Palette",
"settings.Comfy.EditAttention.Delta": "Ctrl+up/down precision",
"settings.Comfy.InvertMenuScrolling": "Invert Menu Scrolling",
"settings.Comfy.LinkRenderMode": "Link Render Mode",
"settings.Comfy.NodeSuggestions.number": "Number of nodes suggestions",
"settings.Comfy.SnapToGrid.GridSize": "Grid Size",
"settings.Comfy.Logging.Enabled": "Comfy.Logging.Enabled",
"settings.Comfy.MenuPosition": "Save menu position",
"settings.Comfy.ColorPalette.export": "Export",
"settings.Comfy.ColorPalette.import": "Import",
"settings.Comfy.ColorPalette.template": "Template",
"settings.Comfy.ColorPalette.delete": "Delete",
}
}

125
web/i18n/zh_CN.js Normal file
View File

@ -0,0 +1,125 @@
export default {
translation: {
"ui.queue_btn": "冲冲冲",
"ui.queue_front_btn": "插队冲冲冲",
"ui.view_queue_btn": "查看队列",
"ui.view_history_btn": "查看历史",
"ui.save_btn": "保存",
"ui.load_btn": "加载",
"ui.refresh_btn": "刷新",
"ui.clipspace_btn": "Clipspace",
"ui.clear_btn": "清空",
"ui.load_default_btn": "加载默认配置",
"ui.close_btn": "关闭",
"ui.queue_size": "队列数量: ",
"ui.extra_options": "额外选项",
"ui.settings.title": "设置",
"ui.canvas_menu_add_node": "添加节点",
"ui.canvas_menu_add_group": "添加组",
"ui.node_panel.header.properties": "属性",
"ui.node_panel.header.title": "标题",
"ui.node_panel.header.mode": "模式",
"ui.node_panel.header.color": "颜色",
"node.title.KSampler": "采样器",
"node.title.KSamplerAdvanced": "采样器 (高级)",
// Loaders
"node.title.CheckpointLoader": "Load Checkpoint (With Config)",
"node.title.CheckpointLoaderSimple": "加载模型",
"node.title.VAELoader": "Load VAE",
"node.title.LoraLoader": "Load LoRA",
"node.title.CLIPLoader": "Load CLIP",
"node.title.ControlNetLoader": "Load ControlNet Model",
"node.title.DiffControlNetLoader": "Load ControlNet Model (diff)",
"node.title.StyleModelLoader": "Load Style Model",
"node.title.CLIPVisionLoader": "Load CLIP Vision",
"node.title.UpscaleModelLoader": "Load Upscale Model",
// Conditioning
"node.title.CLIPVisionEncode": "CLIP Vision Encode",
"node.title.StyleModelApply": "Apply Style Model",
"node.title.CLIPTextEncode": "CLIP Text Encode (Prompt)",
"node.title.CLIPSetLastLayer": "CLIP Set Last Layer",
"node.title.ConditioningCombine": "Conditioning (Combine)",
"node.title.ConditioningAverage ": "Conditioning (Average)",
"node.title.ConditioningConcat": "Conditioning (Concat)",
"node.title.ConditioningSetArea": "Conditioning (Set Area)",
"node.title.ConditioningSetMask": "Conditioning (Set Mask)",
"node.title.ControlNetApply": "Apply ControlNet",
"node.title.ControlNetApplyAdvanced": "Apply ControlNet (Advanced)",
// Latent
"node.title.VAEEncodeForInpaint": "VAE Encode (for Inpainting)",
"node.title.SetLatentNoiseMask": "Set Latent Noise Mask",
"node.title.VAEDecode": "VAE Decode",
"node.title.VAEEncode": "VAE Encode",
"node.title.LatentRotate": "Rotate Latent",
"node.title.LatentFlip": "Flip Latent",
"node.title.LatentCrop": "Crop Latent",
"node.title.EmptyLatentImage": "Empty Latent Image",
"node.title.LatentUpscale": "Upscale Latent",
"node.title.LatentUpscaleBy": "Upscale Latent By",
"node.title.LatentComposite": "Latent Composite",
"node.title.LatentBlend": "Latent Blend",
"LatentFromBatch": "Latent From Batch",
"node.title.RepeatLatentBatch": "Repeat Latent Batch",
// Image
"node.title.SaveImage": "Save Image",
"node.title.PreviewImage": "Preview Image",
"node.title.LoadImage": "Load Image",
"node.title.LoadImageMask": "Load Image (as Mask)",
"node.title.ImageScale": "Upscale Image",
"node.title.ImageScaleBy": "Upscale Image By",
"node.title.ImageUpscaleWithModel": "Upscale Image (using Model)",
"node.title.ImageInvert": "Invert Image",
"node.title.ImagePadForOutpaint": "Pad Image for Outpainting",
// _for_testing
"node.title.VAEDecodeTiled": "VAE Decode (Tiled)",
"node.title.VAEEncodeTiled": "VAE Encode (Tiled)",
"node.input.SaveImage.filename_prefix": "文件名前缀",
"node.input.SaveImage.images": "图片",
"node.output.CheckpointLoaderSimple.MODEL": "模型",
"category.conditioning": "可调参数",
"category.loaders": "加载器",
"category.latent": "潜在",
"category.latent/inpaint": "潜在/修复",
"category.latent/batch": "潜在/批量",
"category.image": "图像",
"category.mask": "遮罩",
"category.image/upscaling": "图像/外扩",
"category.sampling": "采样",
"category._for_testing": "测试",
"category.latent/transform": "潜在/转换",
"category.advanced/loaders": "高级/加载器",
"category.conditioning/style_model": "可调参数/风格模型",
"category.conditioning/gligen": "可调参数/gligen",
"category.advanced/loaders/deprecated": "高级/加载器/已弃用",
"category.advanced/conditioning": "高级/可调参数",
"category.image/postprocessing": "图像/后期处理",
"category.advanced/model_merging": "高级/模型合并",
"category.image/preprocessors": "图像/前期处理",
"category.utils": "工具",
"settings.Comfy.ConfirmClear": "清空工作流需要确认",
"settings.Comfy.PromptFilename": "Prompt for filename when saving workflow",
"settings.Comfy.PreviewFormat": "预览图格式和压缩尺寸, e.g. webp, jpeg, webp;50, etc.",
"settings.Comfy.DisableSliders": "Disable sliders.",
"settings.Comfy.DevMode": "启用开发模式",
"settings.Comfy.ColorPalette": "主题",
"settings.Comfy.EditAttention.Delta": "Ctrl+up/down precision",
"settings.Comfy.InvertMenuScrolling": "反转滚动",
"settings.Comfy.LinkRenderMode": "链接渲染模式",
"settings.Comfy.NodeSuggestions.number": "Number of nodes suggestions",
"settings.Comfy.SnapToGrid.GridSize": "单元格尺寸",
"settings.Comfy.Logging.Enabled": "记录日志",
"settings.Comfy.MenuPosition": "保存菜单位置",
"settings.Comfy.ColorPalette.export": "导出",
"settings.Comfy.ColorPalette.import": "导入",
"settings.Comfy.ColorPalette.template": "模版",
"settings.Comfy.ColorPalette.delete": "删除",
}
}

View File

@ -6,6 +6,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel="stylesheet" type="text/css" href="./lib/litegraph.css" />
<link rel="stylesheet" type="text/css" href="./style.css" />
<script type="text/javascript" src="./lib/i18next.js"></script>
<script type="text/javascript" src="./lib/i18nextBrowserLanguageDetector.js"></script>
<script type="text/javascript" src="./lib/litegraph.core.js"></script>
<script type="text/javascript" src="./lib/litegraph.extensions.js" defer></script>
<script type="module">

2265
web/lib/i18next.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,422 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.i18nextBrowserLanguageDetector = factory());
})(this, (function () { 'use strict';
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _typeof(obj) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
}, _typeof(obj);
}
function _toPrimitive(input, hint) {
if (_typeof(input) !== "object" || input === null) return input;
var prim = input[Symbol.toPrimitive];
if (prim !== undefined) {
var res = prim.call(input, hint || "default");
if (_typeof(res) !== "object") return res;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (hint === "string" ? String : Number)(input);
}
function _toPropertyKey(arg) {
var key = _toPrimitive(arg, "string");
return _typeof(key) === "symbol" ? key : String(key);
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
Object.defineProperty(Constructor, "prototype", {
writable: false
});
return Constructor;
}
var arr = [];
var each = arr.forEach;
var slice = arr.slice;
function defaults(obj) {
each.call(slice.call(arguments, 1), function (source) {
if (source) {
for (var prop in source) {
if (obj[prop] === undefined) obj[prop] = source[prop];
}
}
});
return obj;
}
// eslint-disable-next-line no-control-regex
var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
var serializeCookie = function serializeCookie(name, val, options) {
var opt = options || {};
opt.path = opt.path || '/';
var value = encodeURIComponent(val);
var str = "".concat(name, "=").concat(value);
if (opt.maxAge > 0) {
var maxAge = opt.maxAge - 0;
if (Number.isNaN(maxAge)) throw new Error('maxAge should be a Number');
str += "; Max-Age=".concat(Math.floor(maxAge));
}
if (opt.domain) {
if (!fieldContentRegExp.test(opt.domain)) {
throw new TypeError('option domain is invalid');
}
str += "; Domain=".concat(opt.domain);
}
if (opt.path) {
if (!fieldContentRegExp.test(opt.path)) {
throw new TypeError('option path is invalid');
}
str += "; Path=".concat(opt.path);
}
if (opt.expires) {
if (typeof opt.expires.toUTCString !== 'function') {
throw new TypeError('option expires is invalid');
}
str += "; Expires=".concat(opt.expires.toUTCString());
}
if (opt.httpOnly) str += '; HttpOnly';
if (opt.secure) str += '; Secure';
if (opt.sameSite) {
var sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;
switch (sameSite) {
case true:
str += '; SameSite=Strict';
break;
case 'lax':
str += '; SameSite=Lax';
break;
case 'strict':
str += '; SameSite=Strict';
break;
case 'none':
str += '; SameSite=None';
break;
default:
throw new TypeError('option sameSite is invalid');
}
}
return str;
};
var cookie = {
create: function create(name, value, minutes, domain) {
var cookieOptions = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
path: '/',
sameSite: 'strict'
};
if (minutes) {
cookieOptions.expires = new Date();
cookieOptions.expires.setTime(cookieOptions.expires.getTime() + minutes * 60 * 1000);
}
if (domain) cookieOptions.domain = domain;
document.cookie = serializeCookie(name, encodeURIComponent(value), cookieOptions);
},
read: function read(name) {
var nameEQ = "".concat(name, "=");
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) === ' ') {
c = c.substring(1, c.length);
}
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
}
return null;
},
remove: function remove(name) {
this.create(name, '', -1);
}
};
var cookie$1 = {
name: 'cookie',
lookup: function lookup(options) {
var found;
if (options.lookupCookie && typeof document !== 'undefined') {
var c = cookie.read(options.lookupCookie);
if (c) found = c;
}
return found;
},
cacheUserLanguage: function cacheUserLanguage(lng, options) {
if (options.lookupCookie && typeof document !== 'undefined') {
cookie.create(options.lookupCookie, lng, options.cookieMinutes, options.cookieDomain, options.cookieOptions);
}
}
};
var querystring = {
name: 'querystring',
lookup: function lookup(options) {
var found;
if (typeof window !== 'undefined') {
var search = window.location.search;
if (!window.location.search && window.location.hash && window.location.hash.indexOf('?') > -1) {
search = window.location.hash.substring(window.location.hash.indexOf('?'));
}
var query = search.substring(1);
var params = query.split('&');
for (var i = 0; i < params.length; i++) {
var pos = params[i].indexOf('=');
if (pos > 0) {
var key = params[i].substring(0, pos);
if (key === options.lookupQuerystring) {
found = params[i].substring(pos + 1);
}
}
}
}
return found;
}
};
var hasLocalStorageSupport = null;
var localStorageAvailable = function localStorageAvailable() {
if (hasLocalStorageSupport !== null) return hasLocalStorageSupport;
try {
hasLocalStorageSupport = window !== 'undefined' && window.localStorage !== null;
var testKey = 'i18next.translate.boo';
window.localStorage.setItem(testKey, 'foo');
window.localStorage.removeItem(testKey);
} catch (e) {
hasLocalStorageSupport = false;
}
return hasLocalStorageSupport;
};
var localStorage = {
name: 'localStorage',
lookup: function lookup(options) {
var found;
if (options.lookupLocalStorage && localStorageAvailable()) {
var lng = window.localStorage.getItem(options.lookupLocalStorage);
if (lng) found = lng;
}
return found;
},
cacheUserLanguage: function cacheUserLanguage(lng, options) {
if (options.lookupLocalStorage && localStorageAvailable()) {
window.localStorage.setItem(options.lookupLocalStorage, lng);
}
}
};
var hasSessionStorageSupport = null;
var sessionStorageAvailable = function sessionStorageAvailable() {
if (hasSessionStorageSupport !== null) return hasSessionStorageSupport;
try {
hasSessionStorageSupport = window !== 'undefined' && window.sessionStorage !== null;
var testKey = 'i18next.translate.boo';
window.sessionStorage.setItem(testKey, 'foo');
window.sessionStorage.removeItem(testKey);
} catch (e) {
hasSessionStorageSupport = false;
}
return hasSessionStorageSupport;
};
var sessionStorage = {
name: 'sessionStorage',
lookup: function lookup(options) {
var found;
if (options.lookupSessionStorage && sessionStorageAvailable()) {
var lng = window.sessionStorage.getItem(options.lookupSessionStorage);
if (lng) found = lng;
}
return found;
},
cacheUserLanguage: function cacheUserLanguage(lng, options) {
if (options.lookupSessionStorage && sessionStorageAvailable()) {
window.sessionStorage.setItem(options.lookupSessionStorage, lng);
}
}
};
var navigator$1 = {
name: 'navigator',
lookup: function lookup(options) {
var found = [];
if (typeof navigator !== 'undefined') {
if (navigator.languages) {
// chrome only; not an array, so can't use .push.apply instead of iterating
for (var i = 0; i < navigator.languages.length; i++) {
found.push(navigator.languages[i]);
}
}
if (navigator.userLanguage) {
found.push(navigator.userLanguage);
}
if (navigator.language) {
found.push(navigator.language);
}
}
return found.length > 0 ? found : undefined;
}
};
var htmlTag = {
name: 'htmlTag',
lookup: function lookup(options) {
var found;
var htmlTag = options.htmlTag || (typeof document !== 'undefined' ? document.documentElement : null);
if (htmlTag && typeof htmlTag.getAttribute === 'function') {
found = htmlTag.getAttribute('lang');
}
return found;
}
};
var path = {
name: 'path',
lookup: function lookup(options) {
var found;
if (typeof window !== 'undefined') {
var language = window.location.pathname.match(/\/([a-zA-Z-]*)/g);
if (language instanceof Array) {
if (typeof options.lookupFromPathIndex === 'number') {
if (typeof language[options.lookupFromPathIndex] !== 'string') {
return undefined;
}
found = language[options.lookupFromPathIndex].replace('/', '');
} else {
found = language[0].replace('/', '');
}
}
}
return found;
}
};
var subdomain = {
name: 'subdomain',
lookup: function lookup(options) {
// If given get the subdomain index else 1
var lookupFromSubdomainIndex = typeof options.lookupFromSubdomainIndex === 'number' ? options.lookupFromSubdomainIndex + 1 : 1;
// get all matches if window.location. is existing
// first item of match is the match itself and the second is the first group macht which sould be the first subdomain match
// is the hostname no public domain get the or option of localhost
var language = typeof window !== 'undefined' && window.location && window.location.hostname && window.location.hostname.match(/^(\w{2,5})\.(([a-z0-9-]{1,63}\.[a-z]{2,6})|localhost)/i);
// if there is no match (null) return undefined
if (!language) return undefined;
// return the given group match
return language[lookupFromSubdomainIndex];
}
};
function getDefaults() {
return {
order: ['querystring', 'cookie', 'localStorage', 'sessionStorage', 'navigator', 'htmlTag'],
lookupQuerystring: 'lng',
lookupCookie: 'i18next',
lookupLocalStorage: 'i18nextLng',
lookupSessionStorage: 'i18nextLng',
// cache user language
caches: ['localStorage'],
excludeCacheFor: ['cimode'],
// cookieMinutes: 10,
// cookieDomain: 'myDomain'
convertDetectedLanguage: function convertDetectedLanguage(l) {
return l;
}
};
}
var Browser = /*#__PURE__*/function () {
function Browser(services) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classCallCheck(this, Browser);
this.type = 'languageDetector';
this.detectors = {};
this.init(services, options);
}
_createClass(Browser, [{
key: "init",
value: function init(services) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var i18nOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
this.services = services || {
languageUtils: {}
}; // this way the language detector can be used without i18next
this.options = defaults(options, this.options || {}, getDefaults());
if (typeof this.options.convertDetectedLanguage === 'string' && this.options.convertDetectedLanguage.indexOf('15897') > -1) {
this.options.convertDetectedLanguage = function (l) {
return l.replace('-', '_');
};
}
// backwards compatibility
if (this.options.lookupFromUrlIndex) this.options.lookupFromPathIndex = this.options.lookupFromUrlIndex;
this.i18nOptions = i18nOptions;
this.addDetector(cookie$1);
this.addDetector(querystring);
this.addDetector(localStorage);
this.addDetector(sessionStorage);
this.addDetector(navigator$1);
this.addDetector(htmlTag);
this.addDetector(path);
this.addDetector(subdomain);
}
}, {
key: "addDetector",
value: function addDetector(detector) {
this.detectors[detector.name] = detector;
}
}, {
key: "detect",
value: function detect(detectionOrder) {
var _this = this;
if (!detectionOrder) detectionOrder = this.options.order;
var detected = [];
detectionOrder.forEach(function (detectorName) {
if (_this.detectors[detectorName]) {
var lookup = _this.detectors[detectorName].lookup(_this.options);
if (lookup && typeof lookup === 'string') lookup = [lookup];
if (lookup) detected = detected.concat(lookup);
}
});
detected = detected.map(function (d) {
return _this.options.convertDetectedLanguage(d);
});
if (this.services.languageUtils.getBestMatchFromCodes) return detected; // new i18next v19.5.0
return detected.length > 0 ? detected[0] : null; // a little backward compatibility
}
}, {
key: "cacheUserLanguage",
value: function cacheUserLanguage(lng, caches) {
var _this2 = this;
if (!caches) caches = this.options.caches;
if (!caches) return;
if (this.options.excludeCacheFor && this.options.excludeCacheFor.indexOf(lng) > -1) return;
caches.forEach(function (cacheName) {
if (_this2.detectors[cacheName]) _this2.detectors[cacheName].cacheUserLanguage(lng, _this2.options);
});
}
}]);
return Browser;
}();
Browser.type = 'languageDetector';
return Browser;
}));

View File

@ -12522,7 +12522,7 @@ LGraphNode.prototype.executeAction = function(action)
panel.content.innerHTML = ""; //clear
panel.addHTML("<span class='node_type'>"+node.type+"</span><span class='node_desc'>"+(node.constructor.desc || "")+"</span><span class='separator'></span>");
panel.addHTML("<h3>Properties</h3>");
panel.addHTML(`<h3>${i18next.t("ui.node_panel.header.properties")}</h3>`);
var fUpdate = function(name,value){
graphcanvas.graph.beforeChange(node);
@ -12554,16 +12554,16 @@ LGraphNode.prototype.executeAction = function(action)
graphcanvas.dirty_canvas = true;
};
panel.addWidget( "string", "Title", node.title, {}, fUpdate);
panel.addWidget( "string", i18next.t("ui.node_panel.header.title"), node.title, {}, fUpdate);
panel.addWidget( "combo", "Mode", LiteGraph.NODE_MODES[node.mode], {values: LiteGraph.NODE_MODES}, fUpdate);
panel.addWidget( "combo", i18next.t("ui.node_panel.header.mode"), LiteGraph.NODE_MODES[node.mode], {values: LiteGraph.NODE_MODES}, fUpdate);
var nodeCol = "";
if (node.color !== undefined){
nodeCol = Object.keys(LGraphCanvas.node_colors).filter(function(nK){ return LGraphCanvas.node_colors[nK].color == node.color; });
}
panel.addWidget( "combo", "Color", nodeCol, {values: Object.keys(LGraphCanvas.node_colors)}, fUpdate);
panel.addWidget( "combo", i18next.t("ui.node_panel.header.color"), nodeCol, {values: Object.keys(LGraphCanvas.node_colors)}, fUpdate);
for(var pName in node.properties)
{

View File

@ -5,6 +5,19 @@ import { api } from "./api.js";
import { defaultGraph } from "./defaultGraph.js";
import { getPngMetadata, importA1111, getLatentMetadata } from "./pnginfo.js";
import en from "../i18n/en_US.js"
import cn from "../i18n/zh_CN.js"
i18next.use(i18nextBrowserLanguageDetector).init({
fallbackLng: 'en',
resources: {
"en-US": en,
"en": en,
"zh_CN": cn,
"cn": cn,
},
})
/**
* @typedef {import("types/comfy").ComfyExtension} ComfyExtension
*/
@ -61,7 +74,7 @@ export class ComfyApp {
getPreviewFormatParam() {
let preview_format = this.ui.settings.getSettingValue("Comfy.PreviewFormat");
if(preview_format)
if (preview_format)
return `&preview=${preview_format}`;
else
return "";
@ -72,7 +85,7 @@ export class ComfyApp {
}
static onClipspaceEditorSave() {
if(ComfyApp.clipspace_return_node) {
if (ComfyApp.clipspace_return_node) {
ComfyApp.pasteFromClipspace(ComfyApp.clipspace_return_node);
}
}
@ -83,13 +96,13 @@ export class ComfyApp {
static copyToClipspace(node) {
var widgets = null;
if(node.widgets) {
if (node.widgets) {
widgets = node.widgets.map(({ type, name, value }) => ({ type, name, value }));
}
var imgs = undefined;
var orig_imgs = undefined;
if(node.imgs != undefined) {
if (node.imgs != undefined) {
imgs = [];
orig_imgs = [];
@ -101,7 +114,7 @@ export class ComfyApp {
}
var selectedIndex = 0;
if(node.imageIndex) {
if (node.imageIndex) {
selectedIndex = node.imageIndex;
}
@ -116,30 +129,30 @@ export class ComfyApp {
ComfyApp.clipspace_return_node = null;
if(ComfyApp.clipspace_invalidate_handler) {
if (ComfyApp.clipspace_invalidate_handler) {
ComfyApp.clipspace_invalidate_handler();
}
}
static pasteFromClipspace(node) {
if(ComfyApp.clipspace) {
if (ComfyApp.clipspace) {
// image paste
if(ComfyApp.clipspace.imgs && node.imgs) {
if(node.images && ComfyApp.clipspace.images) {
if(ComfyApp.clipspace['img_paste_mode'] == 'selected') {
if (ComfyApp.clipspace.imgs && node.imgs) {
if (node.images && ComfyApp.clipspace.images) {
if (ComfyApp.clipspace['img_paste_mode'] == 'selected') {
node.images = [ComfyApp.clipspace.images[ComfyApp.clipspace['selectedIndex']]];
}
else {
node.images = ComfyApp.clipspace.images;
}
if(app.nodeOutputs[node.id + ""])
if (app.nodeOutputs[node.id + ""])
app.nodeOutputs[node.id + ""].images = node.images;
}
if(ComfyApp.clipspace.imgs) {
if (ComfyApp.clipspace.imgs) {
// deep-copy to cut link with clipspace
if(ComfyApp.clipspace['img_paste_mode'] == 'selected') {
if (ComfyApp.clipspace['img_paste_mode'] == 'selected') {
const img = new Image();
img.src = ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src;
node.imgs = [img];
@ -147,7 +160,7 @@ export class ComfyApp {
}
else {
const imgs = [];
for(let i=0; i<ComfyApp.clipspace.imgs.length; i++) {
for (let i = 0; i < ComfyApp.clipspace.imgs.length; i++) {
imgs[i] = new Image();
imgs[i].src = ComfyApp.clipspace.imgs[i].src;
node.imgs = imgs;
@ -156,25 +169,25 @@ export class ComfyApp {
}
}
if(node.widgets) {
if(ComfyApp.clipspace.images) {
if (node.widgets) {
if (ComfyApp.clipspace.images) {
const clip_image = ComfyApp.clipspace.images[ComfyApp.clipspace['selectedIndex']];
const index = node.widgets.findIndex(obj => obj.name === 'image');
if(index >= 0) {
if(node.widgets[index].type != 'image' && typeof node.widgets[index].value == "string" && clip_image.filename) {
node.widgets[index].value = (clip_image.subfolder?clip_image.subfolder+'/':'') + clip_image.filename + (clip_image.type?` [${clip_image.type}]`:'');
if (index >= 0) {
if (node.widgets[index].type != 'image' && typeof node.widgets[index].value == "string" && clip_image.filename) {
node.widgets[index].value = (clip_image.subfolder ? clip_image.subfolder + '/' : '') + clip_image.filename + (clip_image.type ? ` [${clip_image.type}]` : '');
}
else {
node.widgets[index].value = clip_image;
}
}
}
if(ComfyApp.clipspace.widgets) {
if (ComfyApp.clipspace.widgets) {
ComfyApp.clipspace.widgets.forEach(({ type, name, value }) => {
const prop = Object.values(node.widgets).find(obj => obj.type === type && obj.name === name);
if (prop && prop.type != 'button') {
if(prop.type != 'image' && typeof prop.value == "string" && value.filename) {
prop.value = (value.subfolder?value.subfolder+'/':'') + value.filename + (value.type?` [${value.type}]`:'');
if (prop.type != 'image' && typeof prop.value == "string" && value.filename) {
prop.value = (value.subfolder ? value.subfolder + '/' : '') + value.filename + (value.type ? ` [${value.type}]` : '');
}
else {
prop.value = value;
@ -285,28 +298,28 @@ export class ComfyApp {
}
// prevent conflict of clipspace content
if(!ComfyApp.clipspace_return_node) {
if (!ComfyApp.clipspace_return_node) {
options.push({
content: "Copy (Clipspace)",
callback: (obj) => { ComfyApp.copyToClipspace(this); }
});
content: "Copy (Clipspace)",
callback: (obj) => { ComfyApp.copyToClipspace(this); }
});
if(ComfyApp.clipspace != null) {
if (ComfyApp.clipspace != null) {
options.push({
content: "Paste (Clipspace)",
callback: () => { ComfyApp.pasteFromClipspace(this); }
});
content: "Paste (Clipspace)",
callback: () => { ComfyApp.pasteFromClipspace(this); }
});
}
if(ComfyApp.isImageNode(this)) {
if (ComfyApp.isImageNode(this)) {
options.push({
content: "Open in MaskEditor",
callback: (obj) => {
ComfyApp.copyToClipspace(this);
ComfyApp.clipspace_return_node = this;
ComfyApp.open_maskeditor();
}
});
content: "Open in MaskEditor",
callback: (obj) => {
ComfyApp.copyToClipspace(this);
ComfyApp.clipspace_return_node = this;
ComfyApp.open_maskeditor();
}
});
}
}
};
@ -316,7 +329,7 @@ export class ComfyApp {
const app = this;
const origNodeOnKeyDown = node.prototype.onKeyDown;
node.prototype.onKeyDown = function(e) {
node.prototype.onKeyDown = function (e) {
if (origNodeOnKeyDown && origNodeOnKeyDown.apply(this, e) === false) {
return false;
}
@ -371,7 +384,7 @@ export class ComfyApp {
if (w.computeSize) {
shiftY += w.computeSize()[1] + 4;
}
else if(w.computedHeight) {
else if (w.computedHeight) {
shiftY += w.computedHeight;
}
else {
@ -616,7 +629,7 @@ export class ComfyApp {
}
// Dragging from Chrome->Firefox there is a file but its a bmp, so ignore that
if (event.dataTransfer.files.length && event.dataTransfer.files[0].type !== "image/bmp") {
await this.handleFile(event.dataTransfer.files[0]);
await this.handleFile(event.dataTransfer.files[0]);
} else {
// Try loading the first URI in the transfer list
const validTypes = ["text/uri-list", "text/x-moz-url"];
@ -676,7 +689,7 @@ export class ComfyApp {
data = data.slice(data.indexOf("workflow\n"));
data = data.slice(data.indexOf("{"));
workflow = JSON.parse(data);
} catch (error) {}
} catch (error) { }
}
if (workflow && workflow.version && workflow.nodes && workflow.extra) {
@ -694,7 +707,7 @@ export class ComfyApp {
const self = this;
const origProcessMouseDown = LGraphCanvas.prototype.processMouseDown;
LGraphCanvas.prototype.processMouseDown = function(e) {
LGraphCanvas.prototype.processMouseDown = function (e) {
const res = origProcessMouseDown.apply(this, arguments);
this.selected_group_moving = false;
@ -714,7 +727,7 @@ export class ComfyApp {
}
const origProcessMouseMove = LGraphCanvas.prototype.processMouseMove;
LGraphCanvas.prototype.processMouseMove = function(e) {
LGraphCanvas.prototype.processMouseMove = function (e) {
const orig_selected_group = this.selected_group;
if (this.selected_group && !this.selected_group_resizing && !this.selected_group_moving) {
@ -739,7 +752,7 @@ export class ComfyApp {
#addProcessKeyHandler() {
const self = this;
const origProcessKey = LGraphCanvas.prototype.processKey;
LGraphCanvas.prototype.processKey = function(e) {
LGraphCanvas.prototype.processKey = function (e) {
const res = origProcessKey.apply(this, arguments);
if (res === false) {
@ -804,7 +817,7 @@ export class ComfyApp {
const self = this;
const origDrawGroups = LGraphCanvas.prototype.drawGroups;
LGraphCanvas.prototype.drawGroups = function(canvas, ctx) {
LGraphCanvas.prototype.drawGroups = function (canvas, ctx) {
if (!this.graph) {
return;
}
@ -891,7 +904,7 @@ export class ComfyApp {
12 + size[0] + 1,
12 + size[1] + LiteGraph.NODE_TITLE_HEIGHT,
[this.round_radius * 2, this.round_radius * 2, 2, 2]
);
);
else if (shape == LiteGraph.CIRCLE_SHAPE)
ctx.arc(size[0] * 0.5, size[1] * 0.5, size[0] * 0.5 + 6, 0, Math.PI * 2);
ctx.strokeStyle = color;
@ -1117,9 +1130,10 @@ export class ComfyApp {
const defs = await api.getNodeDefs();
await this.registerNodesFromDefs(defs);
await this.#invokeExtensionsAsync("registerCustomNodes");
await this.#invokeExtensionsAsync("afterNodesRegistrations")
}
async registerNodesFromDefs(defs) {
async registerNodesFromDefs(defs) {
await this.#invokeExtensionsAsync("addCustomNodeDefs", defs);
// Generate list of known widgets
@ -1135,15 +1149,15 @@ export class ComfyApp {
const node = Object.assign(
function ComfyNode() {
var inputs = nodeData["input"]["required"];
if (nodeData["input"]["optional"] != undefined){
inputs = Object.assign({}, nodeData["input"]["required"], nodeData["input"]["optional"])
if (nodeData["input"]["optional"] != undefined) {
inputs = Object.assign({}, nodeData["input"]["required"], nodeData["input"]["optional"])
}
const config = { minWidth: 1, minHeight: 1 };
for (const inputName in inputs) {
const inputData = inputs[inputName];
const type = inputData[0];
if(inputData[1]?.forceInput) {
if (inputData[1]?.forceInput) {
this.addInput(inputName, type);
} else {
if (Array.isArray(type)) {
@ -1165,7 +1179,7 @@ export class ComfyApp {
for (const o in nodeData["output"]) {
const output = nodeData["output"][o];
const outputName = nodeData["output_name"][o] || output;
const outputShape = nodeData["output_is_list"][o] ? LiteGraph.GRID_SHAPE : LiteGraph.CIRCLE_SHAPE ;
const outputShape = nodeData["output_is_list"][o] ? LiteGraph.GRID_SHAPE : LiteGraph.CIRCLE_SHAPE;
this.addOutput(outputName, output, { shape: outputShape });
}
@ -1430,9 +1444,9 @@ export class ComfyApp {
else if (error.response) {
let message = error.response.error.message;
if (error.response.error.details)
message += ": " + error.response.error.details;
message += ": " + error.response.error.details;
for (const [nodeID, nodeError] of Object.entries(error.response.node_errors)) {
message += "\n" + nodeError.class_type + ":"
message += "\n" + nodeError.class_type + ":"
for (const errorReason of nodeError.errors) {
message += "\n - " + errorReason.message + ": " + errorReason.details
}
@ -1558,22 +1572,22 @@ export class ComfyApp {
async refreshComboInNodes() {
const defs = await api.getNodeDefs();
for(let nodeNum in this.graph._nodes) {
for (let nodeNum in this.graph._nodes) {
const node = this.graph._nodes[nodeNum];
const def = defs[node.type];
// HOTFIX: The current patch is designed to prevent the rest of the code from breaking due to primitive nodes,
// and additional work is needed to consider the primitive logic in the refresh logic.
if(!def)
if (!def)
continue;
for(const widgetNum in node.widgets) {
for (const widgetNum in node.widgets) {
const widget = node.widgets[widgetNum]
if(widget.type == "combo" && def["input"]["required"][widget.name] !== undefined) {
if (widget.type == "combo" && def["input"]["required"][widget.name] !== undefined) {
widget.options.values = def["input"]["required"][widget.name][0];
if(widget.name != 'image' && !widget.options.values.includes(widget.value)) {
if (widget.name != 'image' && !widget.options.values.includes(widget.value)) {
widget.value = widget.options.values[0];
widget.callback(widget.value);
}

View File

@ -1,4 +1,4 @@
import {api} from "./api.js";
import { api } from "./api.js";
export function $el(tag, propsOrChildren, children) {
const split = tag.split(".");
@ -11,7 +11,7 @@ export function $el(tag, propsOrChildren, children) {
if (Array.isArray(propsOrChildren)) {
element.append(...propsOrChildren);
} else {
const {parent, $: cb, dataset, style} = propsOrChildren;
const { parent, $: cb, dataset, style } = propsOrChildren;
delete propsOrChildren.parent;
delete propsOrChildren.$;
delete propsOrChildren.dataset;
@ -178,7 +178,7 @@ export class ComfyDialog {
return [
$el("button", {
type: "button",
textContent: "Close",
textContent: i18next.t("ui.close_btn"),
onclick: () => this.close(),
}),
];
@ -206,11 +206,11 @@ class ComfySettingsDialog extends ComfyDialog {
parent: document.body,
}, [
$el("table.comfy-modal-content.comfy-table", [
$el("caption", {textContent: "Settings"}),
$el("tbody", {$: (tbody) => (this.textElement = tbody)}),
$el("caption", { textContent: i18next.t("ui.settings.title") }),
$el("tbody", { $: (tbody) => (this.textElement = tbody) }),
$el("button", {
type: "button",
textContent: "Close",
textContent: i18next.t("ui.close_btn"),
style: {
cursor: "pointer",
},
@ -234,7 +234,7 @@ class ComfySettingsDialog extends ComfyDialog {
localStorage[settingId] = JSON.stringify(value);
}
addSetting({id, name, type, defaultValue, onChange, attrs = {}, tooltip = "", options = undefined}) {
addSetting({ id, name, type, defaultValue, onChange, attrs = {}, tooltip = "", options = undefined }) {
if (!id) {
throw new Error("Settings must have an ID");
}
@ -270,7 +270,7 @@ class ComfySettingsDialog extends ComfyDialog {
$el("label", {
for: htmlID,
classList: [tooltip !== "" ? "comfy-tooltip-indicator" : ""],
textContent: name,
textContent: i18next.t(`settings.${id}`),
})
]);
@ -337,7 +337,7 @@ class ComfySettingsDialog extends ComfyDialog {
value,
id: htmlID,
type: "number",
style: {maxWidth: "4rem"},
style: { maxWidth: "4rem" },
oninput: (e) => {
setter(e.target.value);
e.target.previousElementSibling.value = e.target.value;
@ -417,10 +417,10 @@ class ComfySettingsDialog extends ComfyDialog {
show() {
this.textElement.replaceChildren(
$el("tr", {
style: {display: "none"},
style: { display: "none" },
}, [
$el("th"),
$el("th", {style: {width: "33%"}})
$el("th", { style: { width: "33%" } })
]),
...this.settings.map((s) => s.render()),
)
@ -457,7 +457,7 @@ class ComfyList {
name: "Delete",
cb: () => api.deleteItem(this.#type, item.prompt[1]),
};
return $el("div", {textContent: item.prompt[0] + ": "}, [
return $el("div", { textContent: item.prompt[0] + ": " }, [
$el("button", {
textContent: "Load",
onclick: () => {
@ -486,7 +486,7 @@ class ComfyList {
await this.load();
},
}),
$el("button", {textContent: "Refresh", onclick: () => this.load()}),
$el("button", { textContent: "Refresh", onclick: () => this.load() }),
])
);
}
@ -579,14 +579,14 @@ export class ComfyUI {
id: "comfy-file-input",
type: "file",
accept: ".json,image/png,.latent,.safetensors",
style: {display: "none"},
style: { display: "none" },
parent: document.body,
onchange: () => {
app.handleFile(fileInput.files[0]);
},
});
this.menuContainer = $el("div.comfy-menu", {parent: document.body}, [
this.menuContainer = $el("div.comfy-menu", { parent: document.body }, [
$el("div.drag-handle", {
style: {
overflow: "hidden",
@ -596,16 +596,16 @@ export class ComfyUI {
}
}, [
$el("span.drag-handle"),
$el("span", {$: (q) => (this.queueSize = q)}),
$el("button.comfy-settings-btn", {textContent: "⚙️", onclick: () => this.settings.show()}),
$el("span", { $: (q) => (this.queueSize = q) }),
$el("button.comfy-settings-btn", { textContent: "⚙️", onclick: () => this.settings.show() }),
]),
$el("button.comfy-queue-btn", {
id: "queue-button",
textContent: "Queue Prompt",
textContent: i18next.t("ui.queue_btn"),
onclick: () => app.queuePrompt(0, this.batchCount),
}),
$el("div", {}, [
$el("label", {innerHTML: "Extra options"}, [
$el("label", { innerHTML: i18next.t("ui.extra_options") }, [
$el("input", {
type: "checkbox",
onchange: (i) => {
@ -616,14 +616,14 @@ export class ComfyUI {
}),
]),
]),
$el("div", {id: "extraOptions", style: {width: "100%", display: "none"}}, [
$el("label", {innerHTML: "Batch count"}, [
$el("div", { id: "extraOptions", style: { width: "100%", display: "none" } }, [
$el("label", { innerHTML: "Batch count" }, [
$el("input", {
id: "batchCountInputNumber",
type: "number",
value: this.batchCount,
min: "1",
style: {width: "35%", "margin-left": "0.4em"},
style: { width: "35%", "margin-left": "0.4em" },
oninput: (i) => {
this.batchCount = i.target.value;
document.getElementById("batchCountInputRange").value = this.batchCount;
@ -651,13 +651,13 @@ export class ComfyUI {
$el("div.comfy-menu-btns", [
$el("button", {
id: "queue-front-button",
textContent: "Queue Front",
textContent: i18next.t("ui.queue_front_btn"),
onclick: () => app.queuePrompt(-1, this.batchCount)
}),
$el("button", {
$: (b) => (this.queue.button = b),
id: "comfy-view-queue-button",
textContent: "View Queue",
textContent: i18next.t("ui.view_queue_btn"),
onclick: () => {
this.history.hide();
this.queue.toggle();
@ -666,7 +666,7 @@ export class ComfyUI {
$el("button", {
$: (b) => (this.history.button = b),
id: "comfy-view-history-button",
textContent: "View History",
textContent: i18next.t("ui.view_history_btn"),
onclick: () => {
this.queue.hide();
this.history.toggle();
@ -677,7 +677,7 @@ export class ComfyUI {
this.history.element,
$el("button", {
id: "comfy-save-button",
textContent: "Save",
textContent: i18next.t("ui.save_btn"),
onclick: () => {
let filename = "workflow.json";
if (promptFilename.value) {
@ -688,12 +688,12 @@ export class ComfyUI {
}
}
const json = JSON.stringify(app.graph.serialize(), null, 2); // convert the data to a JSON string
const blob = new Blob([json], {type: "application/json"});
const blob = new Blob([json], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = $el("a", {
href: url,
download: filename,
style: {display: "none"},
style: { display: "none" },
parent: document.body,
});
a.click();
@ -706,7 +706,7 @@ export class ComfyUI {
$el("button", {
id: "comfy-dev-save-api-button",
textContent: "Save (API Format)",
style: {width: "100%", display: "none"},
style: { width: "100%", display: "none" },
onclick: () => {
let filename = "workflow_api.json";
if (promptFilename.value) {
@ -716,14 +716,14 @@ export class ComfyUI {
filename += ".json";
}
}
app.graphToPrompt().then(p=>{
app.graphToPrompt().then(p => {
const json = JSON.stringify(p.output, null, 2); // convert the data to a JSON string
const blob = new Blob([json], {type: "application/json"});
const blob = new Blob([json], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = $el("a", {
href: url,
download: filename,
style: {display: "none"},
style: { display: "none" },
parent: document.body,
});
a.click();
@ -734,15 +734,15 @@ export class ComfyUI {
});
},
}),
$el("button", {id: "comfy-load-button", textContent: "Load", onclick: () => fileInput.click()}),
$el("button", { id: "comfy-load-button", textContent: i18next.t("ui.load_btn"), onclick: () => fileInput.click() }),
$el("button", {
id: "comfy-refresh-button",
textContent: "Refresh",
textContent: i18next.t("ui.refresh_btn"),
onclick: () => app.refreshComboInNodes()
}),
$el("button", {id: "comfy-clipspace-button", textContent: "Clipspace", onclick: () => app.openClipspace()}),
$el("button", { id: "comfy-clipspace-button", textContent: i18next.t("ui.clipspace_btn"), onclick: () => app.openClipspace() }),
$el("button", {
id: "comfy-clear-button", textContent: "Clear", onclick: () => {
id: "comfy-clear-button", textContent: i18next.t("ui.clear_btn"), onclick: () => {
if (!confirmClear.value || confirm("Clear workflow?")) {
app.clean();
app.graph.clear();
@ -750,7 +750,7 @@ export class ComfyUI {
}
}),
$el("button", {
id: "comfy-load-default-button", textContent: "Load Default", onclick: () => {
id: "comfy-load-default-button", textContent: i18next.t("ui.load_default_btn"), onclick: () => {
if (!confirmClear.value || confirm("Load default workflow?")) {
app.loadGraphData()
}
@ -763,16 +763,16 @@ export class ComfyUI {
name: "Enable Dev mode Options",
type: "boolean",
defaultValue: false,
onChange: function(value) { document.getElementById("comfy-dev-save-api-button").style.display = value ? "block" : "none"},
onChange: function (value) { document.getElementById("comfy-dev-save-api-button").style.display = value ? "block" : "none" },
});
dragElement(this.menuContainer, this.settings);
this.setStatus({exec_info: {queue_remaining: "X"}});
this.setStatus({ exec_info: { queue_remaining: "X" } });
}
setStatus(status) {
this.queueSize.textContent = "Queue size: " + (status ? status.exec_info.queue_remaining : "ERR");
this.queueSize.textContent = i18next.t("ui.queue_size") + (status ? status.exec_info.queue_remaining : "ERR");
if (status) {
if (
this.lastQueueSize != 0 &&