diff --git a/packages/cli/src/NodeTypes.ts b/packages/cli/src/NodeTypes.ts index ff4e8c027c..094ca41cec 100644 --- a/packages/cli/src/NodeTypes.ts +++ b/packages/cli/src/NodeTypes.ts @@ -5,6 +5,7 @@ import { INodeType, INodeTypeData, + INodeTypeDescription, INodeTypes, INodeVersionedType, NodeHelpers, @@ -18,7 +19,7 @@ class NodeTypesClass implements INodeTypes { // polling nodes the polling times // eslint-disable-next-line no-restricted-syntax for (const nodeTypeData of Object.values(nodeTypes)) { - const nodeType = NodeHelpers.getVersionedTypeNode(nodeTypeData.type); + const nodeType = NodeHelpers.getVersionedNodeType(nodeTypeData.type); const applyParameters = NodeHelpers.getSpecialNodeParameters(nodeType); if (applyParameters.length) { @@ -39,11 +40,26 @@ class NodeTypesClass implements INodeTypes { return this.nodeTypes[nodeType].type; } + getWithPath( + nodeTypeName: string, + version: number, + ): { description: INodeTypeDescription } & { sourcePath: string } { + const nodeType = this.nodeTypes[nodeTypeName]; + + if (!nodeType) { + throw new Error(`Unknown node type: ${nodeTypeName}`); + } + + const { description } = NodeHelpers.getVersionedNodeType(nodeType.type, version); + + return { description: { ...description }, sourcePath: nodeType.sourcePath }; + } + getByNameAndVersion(nodeType: string, version?: number): INodeType { if (this.nodeTypes[nodeType] === undefined) { throw new Error(`The node-type "${nodeType}" is not known!`); } - return NodeHelpers.getVersionedTypeNode(this.nodeTypes[nodeType].type, version); + return NodeHelpers.getVersionedNodeType(this.nodeTypes[nodeType].type, version); } } diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index 98d7fd8af1..69c6dcb527 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -24,8 +24,9 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable no-restricted-syntax */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable import/no-dynamic-require */ import * as express from 'express'; -import { readFileSync } from 'fs'; +import { readFileSync, existsSync } from 'fs'; import { dirname as pathDirname, join as pathJoin, resolve as pathResolve } from 'path'; import { FindManyOptions, getConnectionManager, In, IsNull, LessThanOrEqual, Not } from 'typeorm'; import * as bodyParser from 'body-parser'; @@ -144,6 +145,7 @@ import { InternalHooksManager } from './InternalHooksManager'; import { TagEntity } from './databases/entities/TagEntity'; import { WorkflowEntity } from './databases/entities/WorkflowEntity'; import { NameRequest } from './WorkflowHelpers'; +import { getTranslationPath } from './TranslationHelpers'; require('body-parser-xml')(bodyParser); @@ -1152,13 +1154,13 @@ class App { if (onlyLatest) { allNodes.forEach((nodeData) => { - const nodeType = NodeHelpers.getVersionedTypeNode(nodeData); + const nodeType = NodeHelpers.getVersionedNodeType(nodeData); const nodeInfo: INodeTypeDescription = getNodeDescription(nodeType); returnData.push(nodeInfo); }); } else { allNodes.forEach((nodeData) => { - const allNodeTypes = NodeHelpers.getVersionedTypeNodeAll(nodeData); + const allNodeTypes = NodeHelpers.getVersionedNodeTypeAll(nodeData); allNodeTypes.forEach((element) => { const nodeInfo: INodeTypeDescription = getNodeDescription(element); returnData.push(nodeInfo); @@ -1179,15 +1181,28 @@ class App { const nodeInfos = _.get(req, 'body.nodeInfos', []) as INodeTypeNameVersion[]; const nodeTypes = NodeTypes(); - const returnData: INodeTypeDescription[] = []; - nodeInfos.forEach((nodeInfo) => { - const nodeType = nodeTypes.getByNameAndVersion(nodeInfo.name, nodeInfo.version); - if (nodeType?.description) { - returnData.push(nodeType.description); - } - }); + const language = config.get('defaultLocale') ?? req.headers['accept-language'] ?? 'en'; - return returnData; + if (language === 'en') { + return nodeInfos.reduce((acc, { name, version }) => { + const { description } = nodeTypes.getByNameAndVersion(name, version); + if (description) acc.push(description); + return acc; + }, []); + } + + // add node translations where available + return nodeInfos.reduce((acc, { name, version }) => { + const { description, sourcePath } = nodeTypes.getWithPath(name, version); + const mainTranslationPath = getTranslationPath(sourcePath, language); + + if (description && existsSync(mainTranslationPath)) { + description.translation = require(mainTranslationPath); + } + + if (description) acc.push(description); + return acc; + }, []); }, ), ); diff --git a/packages/cli/src/TranslationHelpers.ts b/packages/cli/src/TranslationHelpers.ts new file mode 100644 index 0000000000..00cc7bcbae --- /dev/null +++ b/packages/cli/src/TranslationHelpers.ts @@ -0,0 +1,8 @@ +import { join, dirname } from 'path'; + +/** + * Retrieve the path to the translation file for a node. + */ +export function getTranslationPath(nodeSourcePath: string, language: string): string { + return join(dirname(nodeSourcePath), 'translations', `${language}.js`); +} diff --git a/packages/core/test/Helpers.ts b/packages/core/test/Helpers.ts index eb59201828..a25ff73ad5 100644 --- a/packages/core/test/Helpers.ts +++ b/packages/core/test/Helpers.ts @@ -726,7 +726,7 @@ class NodeTypesClass implements INodeTypes { async init(nodeTypes: INodeTypeData): Promise {} getAll(): INodeType[] { - return Object.values(this.nodeTypes).map((data) => NodeHelpers.getVersionedTypeNode(data.type)); + return Object.values(this.nodeTypes).map((data) => NodeHelpers.getVersionedNodeType(data.type)); } getByName(nodeType: string): INodeType { @@ -734,7 +734,7 @@ class NodeTypesClass implements INodeTypes { } getByNameAndVersion(nodeType: string, version?: number): INodeType { - return NodeHelpers.getVersionedTypeNode(this.nodeTypes[nodeType].type, version); + return NodeHelpers.getVersionedNodeType(this.nodeTypes[nodeType].type, version); } } diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts index 055603a471..6489570e11 100644 --- a/packages/editor-ui/src/Interface.ts +++ b/packages/editor-ui/src/Interface.ts @@ -584,6 +584,7 @@ export interface IRootState { activeActions: string[]; activeNode: string | null; baseUrl: string; + credentialTextRenderKeys: { nodeType: string; credentialType: string; } | null; defaultLocale: string; endpointWebhook: string; endpointWebhookTest: string; diff --git a/packages/editor-ui/src/components/CodeEdit.vue b/packages/editor-ui/src/components/CodeEdit.vue index 8aa76f7b62..12036dc0a2 100644 --- a/packages/editor-ui/src/components/CodeEdit.vue +++ b/packages/editor-ui/src/components/CodeEdit.vue @@ -1,8 +1,8 @@