diff --git a/.github/workflows/i18n-node-defs.yaml b/.github/workflows/i18n-node-defs.yaml new file mode 100644 index 000000000..68f727a7e --- /dev/null +++ b/.github/workflows/i18n-node-defs.yaml @@ -0,0 +1,47 @@ +name: Update Node Definitions Locales + +on: + workflow_dispatch: + inputs: + trigger_type: + description: 'Type of trigger (manual or automatic)' + required: false + type: string + default: 'manual' + +jobs: + update-locales: + runs-on: ubuntu-latest + steps: + - uses: Comfy-Org/ComfyUI_frontend_setup_action@v2.1 + - name: Install Playwright Browsers + run: npx playwright install chromium --with-deps + working-directory: ComfyUI_frontend + - name: Start dev server + # Run electron dev server as it is a superset of the web dev server + # We do want electron specific UIs to be translated. + run: npm run dev:electron & + working-directory: ComfyUI_frontend + - name: Update en.json + run: npm run collect-i18n -- scripts/collect-i18n-node-defs.ts + env: + PLAYWRIGHT_TEST_URL: http://localhost:5173 + working-directory: ComfyUI_frontend + - name: Update translations + run: npm run locale + env: + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + working-directory: ComfyUI_frontend + - name: Create Pull Request + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.PR_GH_TOKEN }} + commit-message: "Update locales for node definitions" + title: "Update locales for node definitions" + body: | + Automated PR to update locales for node definitions + + This PR was created automatically by the frontend update workflow. + branch: update-locales-node-defs-{{ github.event.inputs.trigger_type }}-{{ github.run_id }} + base: main + labels: dependencies \ No newline at end of file diff --git a/.github/workflows/i18n.yaml b/.github/workflows/i18n.yaml index 437a693c9..ff5b0c92f 100644 --- a/.github/workflows/i18n.yaml +++ b/.github/workflows/i18n.yaml @@ -17,13 +17,12 @@ jobs: run: npm run dev:electron & working-directory: ComfyUI_frontend - name: Update en.json - run: npm run collect-i18n + run: npm run collect-i18n -- scripts/collect-i18n-general.ts env: PLAYWRIGHT_TEST_URL: http://localhost:5173 working-directory: ComfyUI_frontend - name: Update translations - # Pipe output so that it doesn't error out on stdout.clearLine - run: npm run locale 2>&1 | cat + run: npm run locale env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} working-directory: ComfyUI_frontend diff --git a/playwright.i18n.config.ts b/playwright.i18n.config.ts index f6a49ef8f..cf84ce770 100644 --- a/playwright.i18n.config.ts +++ b/playwright.i18n.config.ts @@ -8,7 +8,7 @@ const config: PlaywrightTestConfig = { }, reporter: 'list', timeout: 10000, - testMatch: /collect-i18n\.ts/ + testMatch: /collect-i18n-.*\.ts/ } export default config diff --git a/scripts/collect-i18n.ts b/scripts/collect-i18n-general.ts similarity index 59% rename from scripts/collect-i18n.ts rename to scripts/collect-i18n-general.ts index 5e6fe53ec..68592c411 100644 --- a/scripts/collect-i18n.ts +++ b/scripts/collect-i18n-general.ts @@ -3,14 +3,11 @@ import * as fs from 'fs' import { comfyPageFixture as test } from '../browser_tests/fixtures/ComfyPage' import { CORE_MENU_COMMANDS } from '../src/constants/coreMenuCommands' import { SERVER_CONFIG_ITEMS } from '../src/constants/serverConfig' -import type { ComfyApi } from '../src/scripts/api' import type { ComfyCommandImpl } from '../src/stores/commandStore' -import { ComfyNodeDefImpl } from '../src/stores/nodeDefStore' import type { FormItem, SettingParams } from '../src/types/settingTypes' import { formatCamelCase, normalizeI18nKey } from '../src/utils/formatUtil' const localePath = './src/locales/en/main.json' -const nodeDefsPath = './src/locales/en/nodeDefs.json' const commandsPath = './src/locales/en/commands.json' const settingsPath = './src/locales/en/settings.json' @@ -22,7 +19,7 @@ const extractMenuCommandLocaleStrings = (): Set => { return labels } -test('collect-i18n', async ({ comfyPage }) => { +test('collect-i18n-general', async ({ comfyPage }) => { const commands = ( await comfyPage.page.evaluate(() => { const workspace = window['app'].extensionManager @@ -129,105 +126,6 @@ test('collect-i18n', async ({ comfyPage }) => { ]) ) - // Node Definitions - const nodeDefs: ComfyNodeDefImpl[] = Object.values( - await comfyPage.page.evaluate(async () => { - const api = window['app'].api as ComfyApi - return await api.getNodeDefs() - }) - ).map((def) => new ComfyNodeDefImpl(def)) - - console.log(`Collected ${nodeDefs.length} node definitions`) - - const allDataTypesLocale = Object.fromEntries( - nodeDefs - .flatMap((nodeDef) => { - const inputDataTypes = Object.values(nodeDef.inputs.all).map( - (inputSpec) => inputSpec.type - ) - const outputDataTypes = nodeDef.outputs.all.map((output) => output.type) - const allDataTypes = [...inputDataTypes, ...outputDataTypes].flatMap( - (type: string) => type.split(',') - ) - return allDataTypes.map((dataType) => [ - normalizeI18nKey(dataType), - dataType - ]) - }) - .sort((a, b) => a[0].localeCompare(b[0])) - ) - - function extractInputs(nodeDef: ComfyNodeDefImpl) { - const inputs = Object.fromEntries( - nodeDef.inputs.all.flatMap((input) => { - const name = input.name - const tooltip = input.tooltip - - if (name === undefined && tooltip === undefined) { - return [] - } - - return [ - [ - normalizeI18nKey(input.name), - { - name, - tooltip - } - ] - ] - }) - ) - return Object.keys(inputs).length > 0 ? inputs : undefined - } - - function extractOutputs(nodeDef: ComfyNodeDefImpl) { - const outputs = Object.fromEntries( - nodeDef.outputs.all.flatMap((output, i) => { - // Ignore data types if they are already translated in allDataTypesLocale. - const name = output.name in allDataTypesLocale ? undefined : output.name - const tooltip = output.tooltip - - if (name === undefined && tooltip === undefined) { - return [] - } - - return [ - [ - i.toString(), - { - name, - tooltip - } - ] - ] - }) - ) - return Object.keys(outputs).length > 0 ? outputs : undefined - } - - const allNodeDefsLocale = Object.fromEntries( - nodeDefs - .sort((a, b) => a.name.localeCompare(b.name)) - .map((nodeDef) => [ - normalizeI18nKey(nodeDef.name), - { - display_name: nodeDef.display_name ?? nodeDef.name, - description: nodeDef.description || undefined, - inputs: extractInputs(nodeDef), - outputs: extractOutputs(nodeDef) - } - ]) - ) - - const allNodeCategoriesLocale = Object.fromEntries( - nodeDefs.flatMap((nodeDef) => - nodeDef.category - .split('/') - .map((category) => [normalizeI18nKey(category), category]) - ) - ) - fs.writeFileSync( localePath, JSON.stringify( @@ -241,16 +139,13 @@ test('collect-i18n', async ({ comfyPage }) => { ...allSettingCategoriesLocale }, serverConfigItems: allServerConfigsLocale, - serverConfigCategories: allServerConfigCategoriesLocale, - dataTypes: allDataTypesLocale, - nodeCategories: allNodeCategoriesLocale + serverConfigCategories: allServerConfigCategoriesLocale }, null, 2 ) ) - fs.writeFileSync(nodeDefsPath, JSON.stringify(allNodeDefsLocale, null, 2)) fs.writeFileSync(commandsPath, JSON.stringify(allCommandsLocale, null, 2)) fs.writeFileSync(settingsPath, JSON.stringify(allSettingsLocale, null, 2)) }) diff --git a/scripts/collect-i18n-node-defs.ts b/scripts/collect-i18n-node-defs.ts new file mode 100644 index 000000000..03ae9b462 --- /dev/null +++ b/scripts/collect-i18n-node-defs.ts @@ -0,0 +1,125 @@ +import * as fs from 'fs' + +import { comfyPageFixture as test } from '../browser_tests/fixtures/ComfyPage' +import type { ComfyApi } from '../src/scripts/api' +import { ComfyNodeDefImpl } from '../src/stores/nodeDefStore' +import { normalizeI18nKey } from '../src/utils/formatUtil' + +const localePath = './src/locales/en/main.json' +const nodeDefsPath = './src/locales/en/nodeDefs.json' + +test('collect-i18n-node-defs', async ({ comfyPage }) => { + const nodeDefs: ComfyNodeDefImpl[] = Object.values( + await comfyPage.page.evaluate(async () => { + const api = window['app'].api as ComfyApi + return await api.getNodeDefs() + }) + ).map((def) => new ComfyNodeDefImpl(def)) + + console.log(`Collected ${nodeDefs.length} node definitions`) + + const allDataTypesLocale = Object.fromEntries( + nodeDefs + .flatMap((nodeDef) => { + const inputDataTypes = Object.values(nodeDef.inputs.all).map( + (inputSpec) => inputSpec.type + ) + const outputDataTypes = nodeDef.outputs.all.map((output) => output.type) + const allDataTypes = [...inputDataTypes, ...outputDataTypes].flatMap( + (type: string) => type.split(',') + ) + return allDataTypes.map((dataType) => [ + normalizeI18nKey(dataType), + dataType + ]) + }) + .sort((a, b) => a[0].localeCompare(b[0])) + ) + + function extractInputs(nodeDef: ComfyNodeDefImpl) { + const inputs = Object.fromEntries( + nodeDef.inputs.all.flatMap((input) => { + const name = input.name + const tooltip = input.tooltip + + if (name === undefined && tooltip === undefined) { + return [] + } + + return [ + [ + normalizeI18nKey(input.name), + { + name, + tooltip + } + ] + ] + }) + ) + return Object.keys(inputs).length > 0 ? inputs : undefined + } + + function extractOutputs(nodeDef: ComfyNodeDefImpl) { + const outputs = Object.fromEntries( + nodeDef.outputs.all.flatMap((output, i) => { + // Ignore data types if they are already translated in allDataTypesLocale. + const name = output.name in allDataTypesLocale ? undefined : output.name + const tooltip = output.tooltip + + if (name === undefined && tooltip === undefined) { + return [] + } + + return [ + [ + i.toString(), + { + name, + tooltip + } + ] + ] + }) + ) + return Object.keys(outputs).length > 0 ? outputs : undefined + } + + const allNodeDefsLocale = Object.fromEntries( + nodeDefs + .sort((a, b) => a.name.localeCompare(b.name)) + .map((nodeDef) => [ + normalizeI18nKey(nodeDef.name), + { + display_name: nodeDef.display_name ?? nodeDef.name, + description: nodeDef.description || undefined, + inputs: extractInputs(nodeDef), + outputs: extractOutputs(nodeDef) + } + ]) + ) + + const allNodeCategoriesLocale = Object.fromEntries( + nodeDefs.flatMap((nodeDef) => + nodeDef.category + .split('/') + .map((category) => [normalizeI18nKey(category), category]) + ) + ) + + const locale = JSON.parse(fs.readFileSync(localePath, 'utf-8')) + fs.writeFileSync( + localePath, + JSON.stringify( + { + ...locale, + dataTypes: allDataTypesLocale, + nodeCategories: allNodeCategoriesLocale + }, + null, + 2 + ) + ) + + fs.writeFileSync(nodeDefsPath, JSON.stringify(allNodeDefsLocale, null, 2)) +})