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:
silentoplayz 2026-07-29 21:13:07 -04:00
parent f998e0881e
commit f9d119d127
4 changed files with 10 additions and 55 deletions

View file

@ -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')

View file

@ -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

View file

@ -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={() => {

View file

@ -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": "",