mirror of
https://github.com/open-webui/open-webui.git
synced 2026-08-28 05:27:35 +00:00
i18n: add the ComfyUI workflow node mapping strings to en-US
Adds the nine strings this PR's admin UI introduces (workflow parsing feedback and the Auto-detected badge) and prunes three keys the restyle made unreachable. Only en-US is touched. The other catalogs are left for the maintainer's release time sync, so this PR does not collide with translation PRs.
This commit is contained in:
parent
f998e0881e
commit
f9d119d127
4 changed files with 10 additions and 55 deletions
|
|
@ -393,8 +393,6 @@ async def get_models(request: Request, user=Depends(get_verified_user)):
|
|||
model_node_id = None
|
||||
|
||||
for node in image_config.COMFYUI_WORKFLOW_NODES:
|
||||
# Support both old ('model') and new ('ClassName::key') type formats.
|
||||
# A node is a model-loader if its key ends with '_name' (e.g. ckpt_name, unet_name).
|
||||
node_type = node.get('type', '')
|
||||
node_key = node.get('key', '')
|
||||
is_model_node = node_type == 'model' or node_key.endswith('_name')
|
||||
|
|
|
|||
|
|
@ -170,7 +170,6 @@ def _apply_workflow_nodes(workflow, nodes, model, payload):
|
|||
node_type = node.type or ''
|
||||
node_key = node.key or ''
|
||||
|
||||
# --- Legacy semantic type names (backward compat) --------------------
|
||||
if node_type == 'model':
|
||||
for node_id in node.node_ids:
|
||||
workflow[node_id]['inputs'][node_key] = model
|
||||
|
|
@ -205,17 +204,13 @@ def _apply_workflow_nodes(workflow, nodes, model, payload):
|
|||
for node_id in node.node_ids:
|
||||
workflow[node_id]['inputs'][node_key] = seed
|
||||
|
||||
# --- New dynamic format: 'ClassName::inputKey' -----------------------
|
||||
elif '::' in node_type:
|
||||
# Derive semantic meaning from the key name
|
||||
for node_id in node.node_ids:
|
||||
if node_id not in workflow:
|
||||
continue
|
||||
if node_key in ('ckpt_name', 'unet_name'):
|
||||
# Model selection
|
||||
workflow[node_id]['inputs'][node_key] = model
|
||||
elif node_key in ('text', 'prompt', 'positive'):
|
||||
# Positive prompt text
|
||||
workflow[node_id]['inputs'][node_key] = payload.prompt
|
||||
elif node_key in ('width',):
|
||||
workflow[node_id]['inputs'][node_key] = payload.width
|
||||
|
|
@ -239,13 +234,10 @@ def _apply_workflow_nodes(workflow, nodes, model, payload):
|
|||
else:
|
||||
workflow[node_id]['inputs'][node_key] = img
|
||||
elif node.value is not None:
|
||||
# Custom static override
|
||||
workflow[node_id]['inputs'][node_key] = node.value
|
||||
elif hasattr(payload, 'extra_params') and payload.extra_params and node_key in payload.extra_params:
|
||||
# API-provided dynamic override
|
||||
workflow[node_id]['inputs'][node_key] = payload.extra_params[node_key]
|
||||
|
||||
# --- Generic static value passthrough --------------------------------
|
||||
else:
|
||||
for node_id in node.node_ids:
|
||||
workflow[node_id]['inputs'][node_key] = node.value
|
||||
|
|
|
|||
|
|
@ -39,20 +39,10 @@
|
|||
|
||||
let showComfyUIWorkflowEditor = false;
|
||||
|
||||
// Dynamic workflow node config — populated automatically by parseAndPopulateWorkflowNodes()
|
||||
let workflowNodesConfig: { type: string; key: string; node_ids: string; class_type: string }[] =
|
||||
[];
|
||||
let lastKnownWorkflowString: string | null = null;
|
||||
|
||||
/**
|
||||
* Scans every node in the parsed ComfyUI API workflow object and builds a configurable
|
||||
* row for each primitive input (string / number / boolean). Array-valued inputs are
|
||||
* wires/links and are intentionally skipped.
|
||||
*
|
||||
* @param workflow - Parsed JSON object (ComfyUI API format).
|
||||
* @param savedNodes - Previously-saved node configs used for reconciliation on load.
|
||||
* @param showToast - Whether to surface success/warning toasts to the user.
|
||||
*/
|
||||
function parseAndPopulateWorkflowNodes(
|
||||
workflow: Record<string, any>,
|
||||
savedNodes: { type: string; key: string; node_ids: string[] | string }[] = [],
|
||||
|
|
@ -64,9 +54,6 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
// Each entry is keyed by "nodeId::class_type::inputKey" so that nodes
|
||||
// sharing the same class and input (e.g. positive vs negative CLIPTextEncode)
|
||||
// are always kept as separate rows rather than merged together.
|
||||
const nodeGroups = new Map<
|
||||
string,
|
||||
{ type: string; key: string; node_ids: string[]; class_type: string }
|
||||
|
|
@ -83,17 +70,13 @@
|
|||
const val = node.inputs[inputKey];
|
||||
const valType = typeof val;
|
||||
|
||||
// Only expose primitive (non-link) inputs
|
||||
if (valType !== 'string' && valType !== 'number' && valType !== 'boolean') continue;
|
||||
|
||||
discoveredPrimitiveCount++;
|
||||
|
||||
// Unique key per node+input — never merges across different node IDs
|
||||
const entryKey = `${nodeId}::${node.class_type}::${inputKey}`;
|
||||
// The "type" stored in COMFYUI_WORKFLOW_NODES uses class_type::inputKey
|
||||
const semanticType = `${node.class_type}::${inputKey}`;
|
||||
|
||||
// Check if this entry had saved node IDs the user configured
|
||||
const saved = savedNodes.find(
|
||||
(s) =>
|
||||
s.type === semanticType &&
|
||||
|
|
@ -104,10 +87,6 @@
|
|||
);
|
||||
|
||||
if (!nodeGroups.has(entryKey)) {
|
||||
// Keys that map to payload.prompt in _apply_workflow_nodes are ambiguous
|
||||
// when multiple nodes share the same key (e.g. positive vs negative
|
||||
// CLIPTextEncode both have key 'text'). Leave node_ids empty for
|
||||
// these so the admin explicitly picks which nodes receive the prompt.
|
||||
const ambiguousKeys = new Set(['text', 'prompt', 'positive']);
|
||||
const autoAssign = !ambiguousKeys.has(inputKey);
|
||||
|
||||
|
|
@ -127,7 +106,6 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
// Convert map → array, joining node_ids to comma-separated string for the UI input fields
|
||||
workflowNodesConfig = Array.from(nodeGroups.values()).map((n) => ({
|
||||
...n,
|
||||
node_ids: n.node_ids.join(',')
|
||||
|
|
@ -152,15 +130,9 @@
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads config.COMFYUI_WORKFLOW, validates it, and triggers node auto-detection.
|
||||
* @param showToast - Surface toasts to the user.
|
||||
* @param isNewImport - When true, ignore previously-saved node IDs (fresh import).
|
||||
*/
|
||||
const parseWorkflowAndUpdateNodes = (showToast = false, isNewImport = false) => {
|
||||
const wfString: string = config.COMFYUI_WORKFLOW ?? '';
|
||||
|
||||
// Skip if nothing changed (unless it's an explicit new import)
|
||||
if (showToast && wfString === lastKnownWorkflowString && !isNewImport) return;
|
||||
|
||||
if (wfString.trim() === '') {
|
||||
|
|
@ -197,7 +169,6 @@
|
|||
|
||||
let showComfyUIEditWorkflowEditor = false;
|
||||
|
||||
// Dynamic edit-workflow node config
|
||||
let editWorkflowNodesConfig: {
|
||||
type: string;
|
||||
key: string;
|
||||
|
|
@ -206,9 +177,6 @@
|
|||
}[] = [];
|
||||
let lastKnownEditWorkflowString: string | null = null;
|
||||
|
||||
/**
|
||||
* Same as parseWorkflowAndUpdateNodes but operates on the edit-workflow config.
|
||||
*/
|
||||
const parseEditWorkflowAndUpdateNodes = (showToast = false, isNewImport = false) => {
|
||||
const wfString: string = config.IMAGES_EDIT_COMFYUI_WORKFLOW ?? '';
|
||||
|
||||
|
|
@ -238,7 +206,6 @@
|
|||
}
|
||||
|
||||
const reconcileWith = isNewImport ? [] : (config.IMAGES_EDIT_COMFYUI_WORKFLOW_NODES ?? []);
|
||||
// Re-use the same parsing function, writing to editWorkflowNodesConfig
|
||||
const savedNodes = reconcileWith;
|
||||
if (!parsed || typeof parsed !== 'object') {
|
||||
editWorkflowNodesConfig = [];
|
||||
|
|
@ -257,12 +224,10 @@
|
|||
const valType = typeof val;
|
||||
if (valType !== 'string' && valType !== 'number' && valType !== 'boolean') continue;
|
||||
|
||||
// Unique key per node+input — never merges across different node IDs
|
||||
const entryKey = `${nodeId}::${node.class_type}::${inputKey}`;
|
||||
const semanticType = `${node.class_type}::${inputKey}`;
|
||||
|
||||
if (!nodeGroups.has(entryKey)) {
|
||||
// Same ambiguous-key logic as parseAndPopulateWorkflowNodes
|
||||
const ambiguousKeys = new Set(['text', 'prompt', 'positive']);
|
||||
const autoAssign = !ambiguousKeys.has(inputKey);
|
||||
|
||||
|
|
@ -370,7 +335,6 @@
|
|||
const saveHandler = async () => {
|
||||
loading = true;
|
||||
|
||||
// Serialize dynamic workflow node configs before saving
|
||||
if (config?.COMFYUI_WORKFLOW) {
|
||||
if (!validateJSON(config?.COMFYUI_WORKFLOW)) {
|
||||
toast.error($i18n.t('Invalid JSON format for ComfyUI Workflow.'));
|
||||
|
|
@ -424,14 +388,12 @@
|
|||
getModels();
|
||||
}
|
||||
|
||||
// Pretty-print stored workflow JSON for the code editor
|
||||
if (config.COMFYUI_WORKFLOW) {
|
||||
try {
|
||||
config.COMFYUI_WORKFLOW = JSON.stringify(JSON.parse(config.COMFYUI_WORKFLOW), null, 2);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
// Auto-parse on load, reconciling with any saved node configs
|
||||
parseWorkflowAndUpdateNodes(false, false);
|
||||
}
|
||||
|
||||
|
|
@ -724,7 +686,6 @@
|
|||
const reader = new FileReader();
|
||||
reader.onload = (ev) => {
|
||||
config.COMFYUI_WORKFLOW = ev.target.result as string;
|
||||
// Auto-detect nodes from fresh import
|
||||
parseWorkflowAndUpdateNodes(true, true);
|
||||
(e.target as HTMLInputElement).value = '';
|
||||
};
|
||||
|
|
@ -774,7 +735,6 @@
|
|||
lang="json"
|
||||
onChange={(e) => {
|
||||
config.COMFYUI_WORKFLOW = e;
|
||||
// Re-detect nodes as the user edits JSON
|
||||
parseWorkflowAndUpdateNodes(false, false);
|
||||
}}
|
||||
onSave={() => {
|
||||
|
|
@ -1048,7 +1008,6 @@
|
|||
const reader = new FileReader();
|
||||
reader.onload = (ev) => {
|
||||
config.IMAGES_EDIT_COMFYUI_WORKFLOW = ev.target.result as string;
|
||||
// Auto-detect nodes from fresh import
|
||||
parseEditWorkflowAndUpdateNodes(true, true);
|
||||
(e.target as HTMLInputElement).value = '';
|
||||
};
|
||||
|
|
@ -1097,7 +1056,6 @@
|
|||
lang="json"
|
||||
onChange={(e) => {
|
||||
config.IMAGES_EDIT_COMFYUI_WORKFLOW = e;
|
||||
// Re-detect nodes as the user edits JSON
|
||||
parseEditWorkflowAndUpdateNodes(false, false);
|
||||
}}
|
||||
onSave={() => {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
"{{NAMES}} reacted with {{REACTION}}": "",
|
||||
"{{user}}'s Chats": "",
|
||||
"{{webUIName}} Backend Required": "",
|
||||
"*Prompt node ID(s) are required for image generation": "",
|
||||
"1 file": "",
|
||||
"1 group": "",
|
||||
"1 hour before": "",
|
||||
|
|
@ -310,6 +309,7 @@
|
|||
"Auto Redirect": "",
|
||||
"Auto-Copy Response to Clipboard": "",
|
||||
"Auto-Create Groups": "",
|
||||
"Auto-detected": "",
|
||||
"Auto-Playback Response": "",
|
||||
"Autocomplete Generation": "",
|
||||
"Autocomplete Generation Input Max Length": "",
|
||||
|
|
@ -1091,6 +1091,7 @@
|
|||
"Error accessing Google Drive: {{error}}": "",
|
||||
"Error accessing media devices.": "",
|
||||
"Error deleting model: {{error}}": "",
|
||||
"Error occurred during workflow parsing.": "",
|
||||
"Error starting recording.": "",
|
||||
"Error unloading model: {{error}}": "",
|
||||
"Error uploading file: {{error}}": "",
|
||||
|
|
@ -1466,6 +1467,8 @@
|
|||
"Invalid JSON format in {{NAME}}": "",
|
||||
"Invalid JSON format in Additional Config": "",
|
||||
"Invalid JSON format in MinerU Parameters": "",
|
||||
"Invalid JSON syntax in ComfyUI Workflow.": "",
|
||||
"Invalid workflow data provided for parsing.": "",
|
||||
"is typing...": "",
|
||||
"Italic": "",
|
||||
"January": "",
|
||||
|
|
@ -1604,8 +1607,6 @@
|
|||
"Map LDAP groups to Open WebUI groups.": "",
|
||||
"Map OAuth claims to Open WebUI groups.": "",
|
||||
"Map OAuth claims to Open WebUI roles.": "",
|
||||
"Map workflow node inputs used for image edits.": "",
|
||||
"Map workflow node inputs used for image generation.": "",
|
||||
"Mapped Source": "",
|
||||
"March": "",
|
||||
"Mark all as read": "",
|
||||
|
|
@ -1803,6 +1804,7 @@
|
|||
"No chats found": "",
|
||||
"No chats found for this user.": "",
|
||||
"No chats found.": "",
|
||||
"No configurable inputs detected. Upload a workflow in API format.": "",
|
||||
"No content": "",
|
||||
"No content found": "",
|
||||
"No content to speak": "",
|
||||
|
|
@ -1867,7 +1869,9 @@
|
|||
"No valves to update": "",
|
||||
"No webhooks yet": "",
|
||||
"Node Ids": "",
|
||||
"Node IDs are auto-detected from your workflow. Adjust them if needed.": "",
|
||||
"None": "",
|
||||
"Not a valid ComfyUI API Workflow JSON format. Make sure to export as API format from ComfyUI.": "",
|
||||
"Not configured": "",
|
||||
"Not factually correct": "",
|
||||
"Not helpful": "",
|
||||
|
|
@ -2948,6 +2952,9 @@
|
|||
"Width in pixels to compress images to. Leave empty for no compression.": "",
|
||||
"Wikipedia": "",
|
||||
"Won": "",
|
||||
"Workflow parsed, but no configurable primitive inputs were found. Ensure you exported in API format.": "",
|
||||
"Workflow parsed. {{count}} configurable input(s) found. Please review the Node IDs._one": "",
|
||||
"Workflow parsed. {{count}} configurable input(s) found. Please review the Node IDs._other": "",
|
||||
"Working Directory": "",
|
||||
"Works together with top-k. A higher value (e.g., 0.95) will lead to more diverse text, while a lower value (e.g., 0.5) will generate more focused and conservative text.": "",
|
||||
"Workspace": "",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue