Minor optimizations

This commit is contained in:
Iván Ovejero 2021-11-20 18:28:05 +01:00
parent d379d7ecf3
commit b4399a1c63
19 changed files with 144 additions and 99 deletions

View file

@ -41,10 +41,9 @@ class NodeTypesClass implements INodeTypes {
} }
/** /**
* Variant of `getByNameAndVersion` that includes the node's source path, * Variant of `getByNameAndVersion` that includes the node's source path, used to locate a node's translations.
* to be used for locating the node's `/translations` dir.
*/ */
getWithPath( getWithSourcePath(
nodeTypeName: string, nodeTypeName: string,
version: number, version: number,
): { description: INodeTypeDescription } & { sourcePath: string } { ): { description: INodeTypeDescription } & { sourcePath: string } {

View file

@ -25,6 +25,8 @@
/* eslint-disable no-restricted-syntax */ /* eslint-disable no-restricted-syntax */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable import/no-dynamic-require */ /* eslint-disable import/no-dynamic-require */
/* eslint-disable no-await-in-loop */
import * as express from 'express'; import * as express from 'express';
import { readFileSync, existsSync } from 'fs'; import { readFileSync, existsSync } from 'fs';
import { dirname as pathDirname, join as pathJoin, resolve as pathResolve } from 'path'; import { dirname as pathDirname, join as pathJoin, resolve as pathResolve } from 'path';
@ -145,7 +147,7 @@ import { InternalHooksManager } from './InternalHooksManager';
import { TagEntity } from './databases/entities/TagEntity'; import { TagEntity } from './databases/entities/TagEntity';
import { WorkflowEntity } from './databases/entities/WorkflowEntity'; import { WorkflowEntity } from './databases/entities/WorkflowEntity';
import { NameRequest } from './WorkflowHelpers'; import { NameRequest } from './WorkflowHelpers';
import { getExpectedNodeTranslationPath } from './TranslationHelpers'; import { getNodeTranslationPath } from './TranslationHelpers';
require('body-parser-xml')(bodyParser); require('body-parser-xml')(bodyParser);
@ -1179,33 +1181,28 @@ class App {
ResponseHelper.send( ResponseHelper.send(
async (req: express.Request, res: express.Response): Promise<INodeTypeDescription[]> => { async (req: express.Request, res: express.Response): Promise<INodeTypeDescription[]> => {
const nodeInfos = _.get(req, 'body.nodeInfos', []) as INodeTypeNameVersion[]; const nodeInfos = _.get(req, 'body.nodeInfos', []) as INodeTypeNameVersion[];
const nodeTypes = NodeTypes();
const language = config.get('defaultLocale') ?? req.headers['accept-language'] ?? 'en'; const language = config.get('defaultLocale') ?? req.headers['accept-language'] ?? 'en';
if (language === 'en') { if (language === 'en') {
return nodeInfos.reduce<INodeTypeDescription[]>((acc, { name, version }) => { return nodeInfos.reduce<INodeTypeDescription[]>((acc, { name, version }) => {
const { description } = nodeTypes.getByNameAndVersion(name, version); const { description } = NodeTypes().getByNameAndVersion(name, version);
acc.push(description); acc.push(description);
return acc; return acc;
}, []); }, []);
} }
const nodeTypesWithTranslations: INodeTypeDescription[] = []; const nodeTypes: INodeTypeDescription[] = [];
for (const { name, version } of nodeInfos) { for (const { name, version } of nodeInfos) {
const { description, sourcePath } = nodeTypes.getWithPath(name, version); const { description, sourcePath } = NodeTypes().getWithSourcePath(name, version);
// eslint-disable-next-line no-await-in-loop const translationPath = await getNodeTranslationPath(sourcePath, language);
const nodeTranslationPath = await getExpectedNodeTranslationPath(sourcePath, language); if (existsSync(translationPath)) {
description.translation = require(translationPath);
if (existsSync(nodeTranslationPath)) {
description.translation = require(nodeTranslationPath);
} }
nodeTypes.push(description);
nodeTypesWithTranslations.push(description);
} }
return nodeTypesWithTranslations; return nodeTypes;
}, },
), ),
); );
@ -2896,6 +2893,12 @@ export async function start(): Promise<void> {
console.log(`n8n ready on ${ADDRESS}, port ${PORT}`); console.log(`n8n ready on ${ADDRESS}, port ${PORT}`);
console.log(`Version: ${versions.cli}`); console.log(`Version: ${versions.cli}`);
const defaultLocale = config.get('defaultLocale');
if (!defaultLocale || defaultLocale !== 'en') {
console.log(`Locale: ${config.get('defaultLocale')}`);
}
await app.externalHooks.run('n8n.ready', [app]); await app.externalHooks.run('n8n.ready', [app]);
const cpus = os.cpus(); const cpus = os.cpus();
const diagnosticInfo: IDiagnosticInfo = { const diagnosticInfo: IDiagnosticInfo = {

View file

@ -26,7 +26,7 @@ async function getMaxVersion(from: string) {
return Math.max(...dirnames.map((d) => parseInt(d.charAt(1), 10))); return Math.max(...dirnames.map((d) => parseInt(d.charAt(1), 10)));
} }
export async function getExpectedNodeTranslationPath( export async function getNodeTranslationPath(
nodeSourcePath: string, nodeSourcePath: string,
language: string, language: string,
): Promise<string> { ): Promise<string> {

View file

@ -203,17 +203,12 @@ export default mixins(renderText, restApi).extend({
}, },
/** /**
* Add to the translation object the node translation * Add to the translation object the node translation for the credential in the modal.
* for the credential being viewed.
*/ */
async addNodeTranslationForCredential() { async addNodeTranslationForCredential() {
// TODO i18n: Check if node translation has already been added (via NodeView)
const { nodeType }: { nodeType: string } = this.$store.getters.credentialTextRenderKeys; const { nodeType }: { nodeType: string } = this.$store.getters.credentialTextRenderKeys;
const version = await this.getCurrentNodeVersion(nodeType); const version = await this.getCurrentNodeVersion(nodeType);
const nodeToBeFetched = [{ name: nodeType, version }]; const nodeToBeFetched = [{ name: nodeType, version }];
const nodesInfo = await this.restApi().getNodesInformation(nodeToBeFetched); const nodesInfo = await this.restApi().getNodesInformation(nodeToBeFetched);
const nodeInfo = nodesInfo.pop(); const nodeInfo = nodesInfo.pop();

View file

@ -78,7 +78,7 @@ export default mixins(renderText).extend({
}); });
}, },
shortNodeType(nodeType: INodeTypeDescription) { shortNodeType(nodeType: INodeTypeDescription) {
return nodeType.name.replace('n8n-nodes-base.', ''); return this.$shortNodeType(nodeType.name);
}, },
}, },
}); });

View file

@ -34,7 +34,7 @@ export default mixins(genericHelpers).extend({
}; };
if (this.keyName === 'name' && this.node.type.startsWith('n8n-nodes-base.')) { if (this.keyName === 'name' && this.node.type.startsWith('n8n-nodes-base.')) {
const shortNodeType = this.node.type.replace('n8n-nodes-base.', ''); const shortNodeType = this.$shortNodeType(this.node.type);
return this.$headerText({ return this.$headerText({
key: `headers.${shortNodeType}.displayName`, key: `headers.${shortNodeType}.displayName`,

View file

@ -115,10 +115,9 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column property="mode" :label="$baseText('executionsList.mode')" width="100" align="center"> <el-table-column property="mode" :label="$baseText('executionsList.mode')" width="100" align="center">
<!-- TODO i18n <template slot-scope="scope"> <template slot-scope="scope">
{{convertToDisplayDate(scope.row.startedAt)}}<br /> {{ $baseText(`executionsList.modes.${scope.row.mode}`) }}
<small v-if="scope.row.id">ID: {{scope.row.id}}</small> </template>
</template> -->
</el-table-column> </el-table-column>
<el-table-column :label="$baseText('executionsList.runningTime')" width="150" align="center"> <el-table-column :label="$baseText('executionsList.runningTime')" width="150" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
@ -256,14 +255,6 @@ export default mixins(
}, },
]; ];
}, },
modes () {
return {
error: this.$baseText('executionsList.modes.error'),
retry: this.$baseText('executionsList.modes.retry'),
manual: this.$baseText('executionsList.modes.manual'),
trigger: this.$baseText('executionsList.modes.trigger'),
};
},
activeExecutions (): IExecutionsCurrentSummaryExtended[] { activeExecutions (): IExecutionsCurrentSummaryExtended[] {
return this.$store.getters.getActiveExecutions; return this.$store.getters.getActiveExecutions;
}, },
@ -542,7 +533,7 @@ export default mixins(
this.finishedExecutions = data.results.map((execution) => { this.finishedExecutions = data.results.map((execution) => {
// @ts-ignore // @ts-ignore
return { ...execution, mode: this.modes[execution.mode] }; return { ...execution, mode: execution.mode };
}); });
this.finishedExecutionsCount = data.count; this.finishedExecutionsCount = data.count;
this.finishedExecutionsCountEstimated = data.estimated; this.finishedExecutionsCountEstimated = data.estimated;
@ -577,7 +568,7 @@ export default mixins(
data.results = data.results.map((execution) => { data.results = data.results.map((execution) => {
// @ts-ignore // @ts-ignore
return { ...execution, mode: this.modes[execution.mode] }; return { ...execution, mode: execution.mode };
}); });
this.finishedExecutions.push.apply(this.finishedExecutions, data.results); this.finishedExecutions.push.apply(this.finishedExecutions, data.results);

View file

@ -469,8 +469,8 @@ export default mixins(
this.$baseText('mainSidebar.confirmMessage.workflowNew.message'), this.$baseText('mainSidebar.confirmMessage.workflowNew.message'),
this.$baseText('mainSidebar.confirmMessage.workflowNew.headline'), this.$baseText('mainSidebar.confirmMessage.workflowNew.headline'),
'warning', 'warning',
this.$baseText('mainSidebar.confirmMessage.workflowNew.confirmButton'), this.$baseText('mainSidebar.confirmMessage.workflowNew.confirmButtonText'),
this.$baseText('mainSidebar.confirmMessage.workflowNew.cancelButton'), this.$baseText('mainSidebar.confirmMessage.workflowNew.cancelButtonText'),
); );
if (importConfirm === true) { if (importConfirm === true) {
this.$store.commit('setStateDirty', false); this.$store.commit('setStateDirty', false);

View file

@ -162,7 +162,7 @@ export default mixins(externalHooks, nodeBase, nodeHelpers, renderText, workflow
return returnStyles; return returnStyles;
}, },
shortNodeType (): string { shortNodeType (): string {
return this.data.type.replace('n8n-nodes-base.', ''); return this.$shortNodeType(this.data.type);
}, },
waiting (): string | undefined { waiting (): string | undefined {
const workflowExecution = this.$store.getters.getWorkflowExecution; const workflowExecution = this.$store.getters.getWorkflowExecution;

View file

@ -49,7 +49,7 @@ export default mixins(renderText).extend({
], ],
computed: { computed: {
shortNodeType() { shortNodeType() {
return this.nodeType.name.replace('n8n-nodes-base.', ''); return this.$shortNodeType(this.nodeType.name);
}, },
}, },
// @ts-ignore // @ts-ignore

View file

@ -97,7 +97,7 @@ export default mixins(
}, },
nodeTypeName(): string { nodeTypeName(): string {
if (this.nodeType) { if (this.nodeType) {
const shortNodeType = this.nodeType.name.replace('n8n-nodes-base.', ''); const shortNodeType = this.$shortNodeType(this.nodeType.name);
return this.$headerText({ return this.$headerText({
key: `headers.${shortNodeType}.displayName`, key: `headers.${shortNodeType}.displayName`,
@ -109,7 +109,7 @@ export default mixins(
}, },
nodeTypeDescription (): string { nodeTypeDescription (): string {
if (this.nodeType && this.nodeType.description) { if (this.nodeType && this.nodeType.description) {
const shortNodeType = this.nodeType.name.replace('n8n-nodes-base.', ''); const shortNodeType = this.$shortNodeType(this.nodeType.name);
return this.$headerText({ return this.$headerText({
key: `headers.${shortNodeType}.description`, key: `headers.${shortNodeType}.description`,

View file

@ -1,7 +1,7 @@
<template> <template>
<div @keydown.stop class="variable-selector-wrapper"> <div @keydown.stop class="variable-selector-wrapper">
<div class="input-wrapper"> <div class="input-wrapper">
<n8n-input placeholder="Variable filter..." v-model="variableFilter" ref="inputField" size="small" type="text"></n8n-input> <n8n-input :placeholder="$baseText('variableSelector.variableFilter')" v-model="variableFilter" ref="inputField" size="small" type="text"></n8n-input>
</div> </div>
<div class="result-wrapper"> <div class="result-wrapper">
@ -525,14 +525,14 @@ export default mixins(
currentNodeData.push( currentNodeData.push(
{ {
name: 'Parameters', name: this.$baseText('variableSelector.parameters'),
options: this.sortOptions(this.getNodeParameters(activeNode.name, initialPath, skipParameter, filterText) as IVariableSelectorOption[]), options: this.sortOptions(this.getNodeParameters(activeNode.name, initialPath, skipParameter, filterText) as IVariableSelectorOption[]),
}, },
); );
returnData.push( returnData.push(
{ {
name: 'Current Node', name: this.$baseText('variableSelector.currentNode'),
options: this.sortOptions(currentNodeData), options: this.sortOptions(currentNodeData),
}, },
); );
@ -546,7 +546,7 @@ export default mixins(
let nodeOptions: IVariableSelectorOption[]; let nodeOptions: IVariableSelectorOption[];
const upstreamNodes = this.workflow.getParentNodes(activeNode.name, inputName); const upstreamNodes = this.workflow.getParentNodes(activeNode.name, inputName);
for (const nodeName of Object.keys(this.workflow.nodes)) { for (const [nodeName, node] of Object.entries(this.workflow.nodes)) {
// Add the parameters of all nodes // Add the parameters of all nodes
// TODO: Later have to make sure that no parameters can be referenced which have expression which use input-data (for nodes which are not parent nodes) // TODO: Later have to make sure that no parameters can be referenced which have expression which use input-data (for nodes which are not parent nodes)
@ -557,7 +557,7 @@ export default mixins(
nodeOptions = [ nodeOptions = [
{ {
name: 'Parameters', name: this.$baseText('variableSelector.parameters'),
options: this.sortOptions(this.getNodeParameters(nodeName, `$node["${nodeName}"].parameter`, undefined, filterText)), options: this.sortOptions(this.getNodeParameters(nodeName, `$node["${nodeName}"].parameter`, undefined, filterText)),
} as IVariableSelectorOption, } as IVariableSelectorOption,
]; ];
@ -570,7 +570,7 @@ export default mixins(
if (tempOptions.length) { if (tempOptions.length) {
nodeOptions = [ nodeOptions = [
{ {
name: 'Context', name: this.$baseText('variableSelector.context'),
options: this.sortOptions(tempOptions), options: this.sortOptions(tempOptions),
} as IVariableSelectorOption, } as IVariableSelectorOption,
]; ];
@ -583,16 +583,21 @@ export default mixins(
if (tempOutputData) { if (tempOutputData) {
nodeOptions.push( nodeOptions.push(
{ {
name: 'Output Data', name: this.$baseText('variableSelector.outputData'),
options: this.sortOptions(tempOutputData), options: this.sortOptions(tempOutputData),
} as IVariableSelectorOption, } as IVariableSelectorOption,
); );
} }
} }
const shortNodeType = this.$shortNodeType(node.type);
allNodesData.push( allNodesData.push(
{ {
name: nodeName, name: this.$headerText({
key: `headers.${shortNodeType}.displayName`,
fallback: nodeName,
}),
options: this.sortOptions(nodeOptions), options: this.sortOptions(nodeOptions),
}, },
); );
@ -600,7 +605,7 @@ export default mixins(
returnData.push( returnData.push(
{ {
name: 'Nodes', name: this.$baseText('variableSelector.nodes'),
options: this.sortOptions(allNodesData), options: this.sortOptions(allNodesData),
}, },
); );

View file

@ -23,17 +23,16 @@ export const genericHelpers = mixins(showMessage, renderText).extend({
displayTimer (msPassed: number, showMs = false): string { displayTimer (msPassed: number, showMs = false): string {
if (msPassed < 60000) { if (msPassed < 60000) {
if (showMs === false) { if (showMs === false) {
return `${Math.floor(msPassed / 1000)} ${this.$baseText('genericHelpers.sec')}`; return `${this.$n(Math.floor(msPassed / 1000), 'decimal')} ${this.$baseText('genericHelpers.sec')}`;
} }
return `${msPassed / 1000} ${this.$baseText('genericHelpers.sec')}`; return `${this.$n(msPassed / 1000, 'decimal')} ${this.$baseText('genericHelpers.sec')}`;
} }
const secondsPassed = Math.floor(msPassed / 1000); const secondsPassed = Math.floor(msPassed / 1000);
const minutesPassed = Math.floor(secondsPassed / 60); const minutesPassed = Math.floor(secondsPassed / 60);
const secondsLeft = (secondsPassed - (minutesPassed * 60)).toString().padStart(2, '0');
return `${minutesPassed}:${secondsLeft} min.`; return `${this.$n(minutesPassed, 'decimal')}:${this.$n(secondsPassed, 'decimal')} ${this.$baseText('genericHelpers.min')}`;
}, },
editAllowedCheck (): boolean { editAllowedCheck (): boolean {
if (this.isReadOnly) { if (this.isReadOnly) {

View file

@ -1,14 +1,16 @@
/* tslint:disable: variable-name */
// import { TranslationPath } from '@/Interface';
import Vue from 'vue'; import Vue from 'vue';
const REUSABLE_TEXT_KEY = 'reusableText'; const REUSABLE_DYNAMIC_TEXT_KEY = 'reusableDynamicText';
const CREDENTIALS_MODAL_KEY = 'credentialsModal'; const CREDENTIALS_MODAL_KEY = 'credentialsModal';
const NODE_VIEW_KEY = 'nodeView'; const NODE_VIEW_KEY = 'nodeView';
export const renderText = Vue.extend({ export const renderText = Vue.extend({
methods: { methods: {
$shortNodeType(longNodeType: string) {
return longNodeType.replace('n8n-nodes-base.', '');
},
/** /**
* Render a string of base text, i.e. a string with a fixed path to the localized value in the base text object. Optionally allows for [interpolation](https://kazupon.github.io/vue-i18n/guide/formatting.html#named-formatting) when the localized value contains a string between curly braces. * Render a string of base text, i.e. a string with a fixed path to the localized value in the base text object. Optionally allows for [interpolation](https://kazupon.github.io/vue-i18n/guide/formatting.html#named-formatting) when the localized value contains a string between curly braces.
*/ */
@ -55,7 +57,7 @@ export const renderText = Vue.extend({
) { ) {
if (['clientId', 'clientSecret'].includes(parameterName)) { if (['clientId', 'clientSecret'].includes(parameterName)) {
return context.__render({ return context.__render({
key: `${REUSABLE_TEXT_KEY}.oauth2.${parameterName}`, key: `${REUSABLE_DYNAMIC_TEXT_KEY}.oauth2.${parameterName}`,
fallback: displayName, fallback: displayName,
}); });
} }

View file

@ -40,8 +40,14 @@ export async function loadLanguage(language?: string) {
return Promise.resolve(setLanguage(language)); return Promise.resolve(setLanguage(language));
} }
const baseText = require(`./locales/${language}`).default; const { numberFormats, ...rest } = require(`./locales/${language}`).default;
i18n.setLocaleMessage(language, baseText);
i18n.setLocaleMessage(language, rest);
if (numberFormats) {
i18n.setNumberFormat(language, numberFormats);
}
loadedLanguages.push(language); loadedLanguages.push(language);
setLanguage(language); setLanguage(language);

View file

@ -1,5 +1,15 @@
export default { export default {
reusableText: { numberFormats: {
decimal: {
style: 'decimal',
},
},
reusableBaseText: {
cancel: '🇩🇪 Cancel',
save: '🇩🇪 Save',
name: '🇩🇪 Name',
},
reusableDynamicText: {
oauth2: { oauth2: {
clientId: '🇩🇪 Client ID', clientId: '🇩🇪 Client ID',
clientSecret: '🇩🇪 Client Secret', clientSecret: '🇩🇪 Client Secret',
@ -120,7 +130,7 @@ export default {
noProperties: '🇩🇪 No properties', noProperties: '🇩🇪 No properties',
}, },
credentialsList: { credentialsList: {
name: '🇩🇪 Name', name: '@:reusableBaseText.name',
type: '🇩🇪 Type', type: '🇩🇪 Type',
credentials: '🇩🇪 Credentials', credentials: '🇩🇪 Credentials',
addNew: '🇩🇪 Add New', addNew: '🇩🇪 Add New',
@ -165,11 +175,11 @@ export default {
setValue: '🇩🇪 Set Value', setValue: '🇩🇪 Set Value',
}, },
duplicateWorkflowDialog: { duplicateWorkflowDialog: {
cancel: '🇩🇪 Cancel', cancel: '@:reusableBaseText.cancel',
chooseOrCreateATag: '🇩🇪 Choose or create a tag', chooseOrCreateATag: '🇩🇪 Choose or create a tag',
duplicateWorkflow: '🇩🇪 Duplicate Workflow', duplicateWorkflow: '🇩🇪 Duplicate Workflow',
enterWorkflowName: '🇩🇪 Enter workflow name', enterWorkflowName: '🇩🇪 Enter workflow name',
save: '🇩🇪 Save', save: '@:reusableBaseText.save',
showMessage: { showMessage: {
message: '🇩🇪 Please enter a name.', message: '🇩🇪 Please enter a name.',
title: '🇩🇪 Name missing', title: '🇩🇪 Name missing',
@ -292,7 +302,7 @@ export default {
filters: '🇩🇪 Filters', filters: '🇩🇪 Filters',
loadMore: '🇩🇪 Load More', loadMore: '🇩🇪 Load More',
mode: '🇩🇪 Mode', mode: '🇩🇪 Mode',
name: '🇩🇪 Name', name: '@:reusableBaseText.name',
openPastExecution: '🇩🇪 Open Past Execution', openPastExecution: '🇩🇪 Open Past Execution',
retryExecution: '🇩🇪 Retry execution', retryExecution: '🇩🇪 Retry execution',
retryOf: '🇩🇪 Retry of', retryOf: '🇩🇪 Retry of',
@ -373,6 +383,14 @@ export default {
result: '🇩🇪 Result', result: '🇩🇪 Result',
variableSelector: '🇩🇪 Variable Selector', variableSelector: '🇩🇪 Variable Selector',
}, },
variableSelector: {
variableFilter: '🇩🇪 Variable filter...',
currentNode: '🇩🇪 Current Node',
parameters: '🇩🇪 Parameters',
nodes: '🇩🇪 Nodes',
outputData: '🇩🇪 Output Data',
context: '🇩🇪 Context',
},
fixedCollectionParameter: { fixedCollectionParameter: {
choose: '🇩🇪 Choose...', choose: '🇩🇪 Choose...',
currentlyNoItemsExist: '🇩🇪 Currently no items exist', currentlyNoItemsExist: '🇩🇪 Currently no items exist',
@ -384,6 +402,7 @@ export default {
}, },
loading: '🇩🇪 Loading', loading: '🇩🇪 Loading',
sec: '🇩🇪 sec.', sec: '🇩🇪 sec.',
min: '🇩🇪 min.',
}, },
mainSidebar: { mainSidebar: {
aboutN8n: '🇩🇪 About n8n', aboutN8n: '🇩🇪 About n8n',
@ -409,7 +428,7 @@ export default {
help: '🇩🇪 Help', help: '🇩🇪 Help',
helpMenuItems: { helpMenuItems: {
documentation: '🇩🇪 Documentation', documentation: '🇩🇪 Documentation',
forum: '🇩🇪 Forum', forum: '🇩🇪 Forum @:mainSidebar.helpMenuItems.documentation',
workflows: '🇩🇪 Workflows', workflows: '🇩🇪 Workflows',
}, },
importFromFile: '🇩🇪 Import from File', importFromFile: '🇩🇪 Import from File',
@ -417,13 +436,13 @@ export default {
new: '🇩🇪 New', new: '🇩🇪 New',
open: '🇩🇪 Open', open: '🇩🇪 Open',
prompt: { prompt: {
cancel: '🇩🇪 Cancel', cancel: '@:reusableBaseText.cancel',
import: '🇩🇪 Import', import: '🇩🇪 Import',
importWorkflowFromUrl: '🇩🇪 Import Workflow from URL', importWorkflowFromUrl: '🇩🇪 Import Workflow from URL',
invalidUrl: '🇩🇪 Invalid URL', invalidUrl: '🇩🇪 Invalid URL',
workflowUrl: '🇩🇪 Workflow URL', workflowUrl: '🇩🇪 Workflow URL',
}, },
save: '🇩🇪 Save', save: '@:reusableBaseText.save',
settings: '🇩🇪 Settings', settings: '🇩🇪 Settings',
showError: { showError: {
stopExecution: { stopExecution: {
@ -584,7 +603,7 @@ export default {
workflowWithIdCouldNotBeFound: '🇩🇪 Workflow with id "{workflowId}" could not be found!', workflowWithIdCouldNotBeFound: '🇩🇪 Workflow with id "{workflowId}" could not be found!',
executesTheWorkflowFromTheStartOrWebhookNode: '🇩🇪 Executes the Workflow from the Start or Webhook Node.', executesTheWorkflowFromTheStartOrWebhookNode: '🇩🇪 Executes the Workflow from the Start or Webhook Node.',
prompt: { prompt: {
cancel: '🇩🇪 Cancel', cancel: '@:reusableBaseText.cancel',
invalidName: '🇩🇪 Invalid Name', invalidName: '🇩🇪 Invalid Name',
newName: '🇩🇪 New Name', newName: '🇩🇪 New Name',
rename: '🇩🇪 Rename', rename: '🇩🇪 Rename',
@ -739,7 +758,7 @@ export default {
showMessage: { showMessage: {
showDetails: '🇩🇪 Show Details', showDetails: '🇩🇪 Show Details',
ok: '🇩🇪 OK', ok: '🇩🇪 OK',
cancel: '🇩🇪 Cancel', cancel: '@:reusableBaseText.cancel',
}, },
pushConnection: { pushConnection: {
showMessage: { showMessage: {
@ -781,7 +800,7 @@ export default {
theNodeContains: '🇩🇪 The node contains {numberOfKb} KB of data.<br />Displaying it could cause problems!<br /><br />If you do decide to display it, avoid the JSON view!', theNodeContains: '🇩🇪 The node contains {numberOfKb} KB of data.<br />Displaying it could cause problems!<br /><br />If you do decide to display it, avoid the JSON view!',
}, },
saveButton: { saveButton: {
save: '🇩🇪 Save', save: '@:reusableBaseText.save',
saving: '🇩🇪 Saving', saving: '🇩🇪 Saving',
saved: '🇩🇪 Saved', saved: '🇩🇪 Saved',
}, },
@ -830,11 +849,11 @@ export default {
noMatchingTagsExist: '🇩🇪 No matching tags exist', noMatchingTagsExist: '🇩🇪 No matching tags exist',
saveChanges: '🇩🇪 Save changes?', saveChanges: '🇩🇪 Save changes?',
areYouSureYouWantToDeleteThisTag: '🇩🇪 Are you sure you want to delete this tag?', areYouSureYouWantToDeleteThisTag: '🇩🇪 Are you sure you want to delete this tag?',
cancel: '🇩🇪 Cancel', cancel: '@:reusableBaseText.cancel',
createTag: '🇩🇪 Create tag', createTag: '🇩🇪 Create tag',
deleteTag: '🇩🇪 Delete tag', deleteTag: '🇩🇪 Delete tag',
editTag: '🇩🇪 Edit Tag', editTag: '🇩🇪 Edit Tag',
name: '🇩🇪 Name', name: '@:reusableBaseText.name',
usage: '🇩🇪 Usage', usage: '🇩🇪 Usage',
}, },
tagsTableHeader: { tagsTableHeader: {
@ -908,7 +927,7 @@ export default {
message: '🇩🇪 When you switch workflows your current workflow changes will be lost.', message: '🇩🇪 When you switch workflows your current workflow changes will be lost.',
}, },
created: '🇩🇪 Created', created: '🇩🇪 Created',
name: '🇩🇪 Name', name: '@:reusableBaseText.name',
openWorkflow: '🇩🇪 Open Workflow', openWorkflow: '🇩🇪 Open Workflow',
searchWorkflows: '🇩🇪 Search workflows...', searchWorkflows: '🇩🇪 Search workflows...',
showError: { showError: {
@ -950,18 +969,18 @@ export default {
hours: '🇩🇪 hours', hours: '🇩🇪 hours',
minutes: '🇩🇪 minutes', minutes: '🇩🇪 minutes',
noWorkflow: '🇩🇪 - No Workflow -', noWorkflow: '🇩🇪 - No Workflow -',
save: '🇩🇪 Save', save: '@:reusableBaseText.save',
saveDataErrorExecution: '🇩🇪 Save Data Error Execution', saveDataErrorExecution: '🇩🇪 Save Data Error Execution',
saveDataErrorExecutionOptions: { saveDataErrorExecutionOptions: {
defaultSave: '🇩🇪 Default - ({defaultValue})', defaultSave: '🇩🇪 Default - ({defaultValue})',
doNotSave: '🇩🇪 Do not save', doNotSave: '🇩🇪 Do not save',
save: '🇩🇪 Save', save: '@:reusableBaseText.save',
}, },
saveDataSuccessExecution: '🇩🇪 Save Data Success Execution', saveDataSuccessExecution: '🇩🇪 Save Data Success Execution',
saveDataSuccessExecutionOptions: { saveDataSuccessExecutionOptions: {
defaultSave: '🇩🇪 Default - ({defaultValue})', defaultSave: '🇩🇪 Default - ({defaultValue})',
doNotSave: '🇩🇪 Do not save', doNotSave: '🇩🇪 Do not save',
save: '🇩🇪 Save', save: '@:reusableBaseText.save',
}, },
saveExecutionProgress: '🇩🇪 Save Execution Progress', saveExecutionProgress: '🇩🇪 Save Execution Progress',
saveExecutionProgressOptions: { saveExecutionProgressOptions: {

View file

@ -1,4 +1,15 @@
export default { export default {
reusableBaseText: {
cancel: 'Cancel',
save: 'Save',
name: 'Name',
},
reusableDynamicText: {
oauth2: {
clientId: 'Client ID',
clientSecret: 'Client Secret',
},
},
nodeCreator: { nodeCreator: {
categoryNames: { categoryNames: {
coreNodes: 'Core Nodes', coreNodes: 'Core Nodes',
@ -114,7 +125,7 @@ export default {
noProperties: 'No properties', noProperties: 'No properties',
}, },
credentialsList: { credentialsList: {
name: 'Name', name: '@:reusableBaseText.name',
type: 'Type', type: 'Type',
credentials: 'Credentials', credentials: 'Credentials',
addNew: 'Add New', addNew: 'Add New',
@ -159,11 +170,11 @@ export default {
setValue: 'Set Value', setValue: 'Set Value',
}, },
duplicateWorkflowDialog: { duplicateWorkflowDialog: {
cancel: 'Cancel', cancel: '@:reusableBaseText.cancel',
chooseOrCreateATag: 'Choose or create a tag', chooseOrCreateATag: 'Choose or create a tag',
duplicateWorkflow: 'Duplicate Workflow', duplicateWorkflow: 'Duplicate Workflow',
enterWorkflowName: 'Enter workflow name', enterWorkflowName: 'Enter workflow name',
save: 'Save', save: '@:reusableBaseText.save',
showMessage: { showMessage: {
message: 'Please enter a name.', message: 'Please enter a name.',
title: 'Name missing', title: 'Name missing',
@ -286,7 +297,7 @@ export default {
filters: 'Filters', filters: 'Filters',
loadMore: 'Load More', loadMore: 'Load More',
mode: 'Mode', mode: 'Mode',
name: 'Name', name: '@:reusableBaseText.name',
openPastExecution: 'Open Past Execution', openPastExecution: 'Open Past Execution',
retryExecution: 'Retry execution', retryExecution: 'Retry execution',
retryOf: 'Retry of', retryOf: 'Retry of',
@ -367,6 +378,14 @@ export default {
result: 'Result', result: 'Result',
variableSelector: 'Variable Selector', variableSelector: 'Variable Selector',
}, },
variableSelector: {
variableFilter: 'Variable filter...',
currentNode: 'Current Node',
parameters: 'Parameters',
nodes: 'Nodes',
outputData: 'Output Data',
context: 'Context',
},
fixedCollectionParameter: { fixedCollectionParameter: {
choose: 'Choose...', choose: 'Choose...',
currentlyNoItemsExist: 'Currently no items exist', currentlyNoItemsExist: 'Currently no items exist',
@ -378,6 +397,7 @@ export default {
}, },
loading: 'Loading', loading: 'Loading',
sec: 'sec.', sec: 'sec.',
min: 'min.',
}, },
mainSidebar: { mainSidebar: {
aboutN8n: 'About n8n', aboutN8n: 'About n8n',
@ -411,13 +431,13 @@ export default {
new: 'New', new: 'New',
open: 'Open', open: 'Open',
prompt: { prompt: {
cancel: 'Cancel', cancel: '@:reusableBaseText.cancel',
import: 'Import', import: 'Import',
importWorkflowFromUrl: 'Import Workflow from URL', importWorkflowFromUrl: 'Import Workflow from URL',
invalidUrl: 'Invalid URL', invalidUrl: 'Invalid URL',
workflowUrl: 'Workflow URL', workflowUrl: 'Workflow URL',
}, },
save: 'Save', save: '@:reusableBaseText.save',
settings: 'Settings', settings: 'Settings',
showError: { showError: {
stopExecution: { stopExecution: {
@ -578,7 +598,7 @@ export default {
workflowWithIdCouldNotBeFound: 'Workflow with id "{workflowId}" could not be found!', workflowWithIdCouldNotBeFound: 'Workflow with id "{workflowId}" could not be found!',
executesTheWorkflowFromTheStartOrWebhookNode: 'Executes the Workflow from the Start or Webhook Node.', executesTheWorkflowFromTheStartOrWebhookNode: 'Executes the Workflow from the Start or Webhook Node.',
prompt: { prompt: {
cancel: 'Cancel', cancel: '@:reusableBaseText.cancel',
invalidName: 'Invalid Name', invalidName: 'Invalid Name',
newName: 'New Name', newName: 'New Name',
rename: 'Rename', rename: 'Rename',
@ -733,7 +753,7 @@ export default {
showMessage: { showMessage: {
showDetails: 'Show Details', showDetails: 'Show Details',
ok: 'OK', ok: 'OK',
cancel: 'Cancel', cancel: '@:reusableBaseText.cancel',
}, },
pushConnection: { pushConnection: {
showMessage: { showMessage: {
@ -775,7 +795,7 @@ export default {
theNodeContains: 'The node contains {numberOfKb} KB of data.<br />Displaying it could cause problems!<br /><br />If you do decide to display it, avoid the JSON view!', theNodeContains: 'The node contains {numberOfKb} KB of data.<br />Displaying it could cause problems!<br /><br />If you do decide to display it, avoid the JSON view!',
}, },
saveButton: { saveButton: {
save: 'Save', save: '@:reusableBaseText.save',
saving: 'Saving', saving: 'Saving',
saved: 'Saved', saved: 'Saved',
}, },
@ -824,11 +844,11 @@ export default {
noMatchingTagsExist: 'No matching tags exist', noMatchingTagsExist: 'No matching tags exist',
saveChanges: 'Save changes?', saveChanges: 'Save changes?',
areYouSureYouWantToDeleteThisTag: 'Are you sure you want to delete this tag?', areYouSureYouWantToDeleteThisTag: 'Are you sure you want to delete this tag?',
cancel: 'Cancel', cancel: '@:reusableBaseText.cancel',
createTag: 'Create tag', createTag: 'Create tag',
deleteTag: 'Delete tag', deleteTag: 'Delete tag',
editTag: 'Edit Tag', editTag: 'Edit Tag',
name: 'Name', name: '@:reusableBaseText.name',
usage: 'Usage', usage: 'Usage',
}, },
tagsTableHeader: { tagsTableHeader: {
@ -902,7 +922,7 @@ export default {
message: 'When you switch workflows your current workflow changes will be lost.', message: 'When you switch workflows your current workflow changes will be lost.',
}, },
created: 'Created', created: 'Created',
name: 'Name', name: '@:reusableBaseText.name',
openWorkflow: 'Open Workflow', openWorkflow: 'Open Workflow',
searchWorkflows: 'Search workflows...', searchWorkflows: 'Search workflows...',
showError: { showError: {
@ -944,18 +964,18 @@ export default {
hours: 'hours', hours: 'hours',
minutes: 'minutes', minutes: 'minutes',
noWorkflow: '- No Workflow -', noWorkflow: '- No Workflow -',
save: 'Save', save: '@:reusableBaseText.save',
saveDataErrorExecution: 'Save Data Error Execution', saveDataErrorExecution: 'Save Data Error Execution',
saveDataErrorExecutionOptions: { saveDataErrorExecutionOptions: {
defaultSave: 'Default - ({defaultValue})', defaultSave: 'Default - ({defaultValue})',
doNotSave: 'Do not save', doNotSave: 'Do not save',
save: 'Save', save: '@:reusableBaseText.save',
}, },
saveDataSuccessExecution: 'Save Data Success Execution', saveDataSuccessExecution: 'Save Data Success Execution',
saveDataSuccessExecutionOptions: { saveDataSuccessExecutionOptions: {
defaultSave: 'Default - ({defaultValue})', defaultSave: 'Default - ({defaultValue})',
doNotSave: 'Do not save', doNotSave: 'Do not save',
save: 'Save', save: '@:reusableBaseText.save',
}, },
saveExecutionProgress: 'Save Execution Progress', saveExecutionProgress: 'Save Execution Progress',
saveExecutionProgressOptions: { saveExecutionProgressOptions: {

View file

@ -458,8 +458,7 @@ export default mixins(
data.workflow.nodes.forEach((node) => { data.workflow.nodes.forEach((node) => {
if (!this.$store.getters.nodeType(node.type)) { if (!this.$store.getters.nodeType(node.type)) {
const name = node.type.replace('n8n-nodes-base.', ''); throw new Error(`The ${this.$shortNodeType(node.type)} node is not supported`);
throw new Error(`The ${name} node is not supported`);
} }
}); });
} catch (error) { } catch (error) {

View file

@ -0,0 +1,7 @@
module.exports = {
github: {
header: {
displayName: '🇩🇪 Start',
},
},
};