mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-27 00:14:55 +00:00
fix: avoid compiling node tooltip metadata
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
import { useEventListener } from '@vueuse/core'
|
||||
import { nextTick, ref } from 'vue'
|
||||
|
||||
import { st } from '@/i18n'
|
||||
import { stRaw } from '@/i18n'
|
||||
import {
|
||||
LiteGraph,
|
||||
isOverNodeInput,
|
||||
@@ -84,7 +84,7 @@ function onIdle() {
|
||||
)
|
||||
if (inputSlot !== -1) {
|
||||
const inputName = node.inputs[inputSlot].name
|
||||
const translatedTooltip = st(
|
||||
const translatedTooltip = stRaw(
|
||||
`nodeDefs.${normalizeI18nKey(node.type ?? '')}.inputs.${normalizeI18nKey(inputName)}.tooltip`,
|
||||
nodeDef?.inputs[inputName]?.tooltip ?? ''
|
||||
)
|
||||
@@ -98,7 +98,7 @@ function onIdle() {
|
||||
[0, 0]
|
||||
)
|
||||
if (outputSlot !== -1) {
|
||||
const translatedTooltip = st(
|
||||
const translatedTooltip = stRaw(
|
||||
`nodeDefs.${normalizeI18nKey(node.type ?? '')}.outputs.${outputSlot}.tooltip`,
|
||||
nodeDef?.outputs[outputSlot]?.tooltip ?? ''
|
||||
)
|
||||
@@ -108,7 +108,7 @@ function onIdle() {
|
||||
const widget = comfyApp.canvas.getWidgetAtCursor()
|
||||
// Dont show for DOM widgets, these use native browser tooltips as we dont get proper mouse events on these
|
||||
if (widget && !isDOMWidget(widget)) {
|
||||
const translatedTooltip = st(
|
||||
const translatedTooltip = stRaw(
|
||||
`nodeDefs.${normalizeI18nKey(node.type ?? '')}.inputs.${normalizeI18nKey(widget.name)}.tooltip`,
|
||||
nodeDef?.inputs[widget.name]?.tooltip ?? ''
|
||||
)
|
||||
|
||||
15
src/i18n.ts
15
src/i18n.ts
@@ -155,6 +155,7 @@ export const i18n = createI18n({
|
||||
|
||||
/** Convenience shorthand: i18n.global */
|
||||
export const { t, te, d } = i18n.global
|
||||
const { tm } = i18n.global
|
||||
|
||||
/**
|
||||
* Safe translation function that returns the fallback message if the key is not found.
|
||||
@@ -166,3 +167,17 @@ export function st(key: string, fallbackMessage: string) {
|
||||
// The normal defaultMsg overload fails in some cases for custom nodes
|
||||
return te(key) ? t(key) : fallbackMessage
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe raw translation function for strings that may contain i18n syntax.
|
||||
*
|
||||
* @param key - The key for the raw locale message.
|
||||
* @param fallbackMessage - The fallback message to use if the key is not found
|
||||
* or the locale message is not a string.
|
||||
*/
|
||||
export function stRaw(key: string, fallbackMessage: string) {
|
||||
if (!te(key)) return fallbackMessage
|
||||
|
||||
const message = tm(key)
|
||||
return typeof message === 'string' ? message : fallbackMessage
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
import { createTestingPinia } from '@pinia/testing'
|
||||
import { setActivePinia } from 'pinia'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import type { SafeWidgetData } from '@/composables/graph/useGraphNodeManager'
|
||||
import { te } from '@/i18n'
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import type { Settings } from '@/schemas/apiSchema'
|
||||
import type { ComfyNodeDef } from '@/schemas/nodeDefSchema'
|
||||
import { useNodeDefStore } from '@/stores/nodeDefStore'
|
||||
|
||||
import { useNodeTooltips } from './useNodeTooltips'
|
||||
|
||||
const jsonTooltip =
|
||||
'Positive point prompts as JSON [{"x": int, "y": int}, ...] (pixel coords)'
|
||||
|
||||
const positiveCoordsTooltipKey =
|
||||
'nodeDefs.SAM3_Detect.inputs.positive_coords.tooltip'
|
||||
|
||||
const positiveCoordsWidget: SafeWidgetData = {
|
||||
name: 'positive_coords',
|
||||
type: 'STRING'
|
||||
}
|
||||
|
||||
const sam3DetectNodeDef: ComfyNodeDef = {
|
||||
name: 'SAM3_Detect',
|
||||
display_name: 'SAM3 Detect',
|
||||
category: 'detection/',
|
||||
python_module: 'comfy_extras.nodes_sam3',
|
||||
description: '',
|
||||
input: {
|
||||
required: {},
|
||||
optional: {
|
||||
positive_coords: [
|
||||
'STRING',
|
||||
{
|
||||
tooltip: jsonTooltip,
|
||||
forceInput: true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
output: [],
|
||||
output_node: false,
|
||||
deprecated: false,
|
||||
experimental: false
|
||||
}
|
||||
|
||||
describe('useNodeTooltips', () => {
|
||||
beforeEach(() => {
|
||||
setActivePinia(createTestingPinia({ stubActions: false }))
|
||||
|
||||
vi.spyOn(useSettingStore(), 'get').mockImplementation(
|
||||
<K extends keyof Settings>(key: K): Settings[K] => {
|
||||
switch (key) {
|
||||
case 'Comfy.EnableTooltips':
|
||||
return true as Settings[K]
|
||||
case 'LiteGraph.Node.TooltipDelay':
|
||||
return 500 as Settings[K]
|
||||
default:
|
||||
return undefined as Settings[K]
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
useNodeDefStore().addNodeDef(sam3DetectNodeDef)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
it('reads JSON examples in node metadata without i18n placeholder errors', () => {
|
||||
const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
|
||||
const { getInputSlotTooltip } = useNodeTooltips('SAM3_Detect')
|
||||
|
||||
// Ensure this exercises the bundled i18n path, not only metadata fallback.
|
||||
expect(te(positiveCoordsTooltipKey)).toBe(true)
|
||||
expect(getInputSlotTooltip('positive_coords')).toBe(jsonTooltip)
|
||||
expect(consoleError).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('reads input-based widget tooltips without i18n placeholder errors', () => {
|
||||
const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
|
||||
const { getWidgetTooltip } = useNodeTooltips('SAM3_Detect')
|
||||
|
||||
expect(te(positiveCoordsTooltipKey)).toBe(true)
|
||||
expect(getWidgetTooltip(positiveCoordsWidget)).toBe(jsonTooltip)
|
||||
expect(consoleError).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -6,7 +6,7 @@ import { computed, ref, unref } from 'vue'
|
||||
import type { MaybeRef } from 'vue'
|
||||
|
||||
import type { SafeWidgetData } from '@/composables/graph/useGraphNodeManager'
|
||||
import { st } from '@/i18n'
|
||||
import { st, stRaw } from '@/i18n'
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import { useNodeDefStore } from '@/stores/nodeDefStore'
|
||||
import { normalizeI18nKey } from '@/utils/formatUtil'
|
||||
@@ -119,7 +119,7 @@ export function useNodeTooltips(nodeType: MaybeRef<string>) {
|
||||
|
||||
const key = `nodeDefs.${normalizeI18nKey(unref(nodeType))}.inputs.${normalizeI18nKey(slotName)}.tooltip`
|
||||
const inputTooltip = nodeDef.value.inputs?.[slotName]?.tooltip ?? ''
|
||||
return st(key, inputTooltip)
|
||||
return stRaw(key, inputTooltip)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,7 +130,7 @@ export function useNodeTooltips(nodeType: MaybeRef<string>) {
|
||||
|
||||
const key = `nodeDefs.${normalizeI18nKey(unref(nodeType))}.outputs.${slotIndex}.tooltip`
|
||||
const outputTooltip = nodeDef.value.outputs?.[slotIndex]?.tooltip ?? ''
|
||||
return st(key, outputTooltip)
|
||||
return stRaw(key, outputTooltip)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +146,7 @@ export function useNodeTooltips(nodeType: MaybeRef<string>) {
|
||||
// Then try input-based tooltip lookup
|
||||
const key = `nodeDefs.${normalizeI18nKey(unref(nodeType))}.inputs.${normalizeI18nKey(widget.name)}.tooltip`
|
||||
const inputTooltip = nodeDef.value.inputs?.[widget.name]?.tooltip ?? ''
|
||||
return st(key, inputTooltip)
|
||||
return stRaw(key, inputTooltip)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user