first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,83 @@
import type {
IDataObject,
IExecuteFunctions,
IHttpRequestMethods,
ILoadOptionsFunctions,
IRequestOptions,
JsonObject,
} from 'n8n-workflow';
import { NodeApiError } from 'n8n-workflow';
import { getGoogleAccessToken } from '../GenericFunctions';
export async function googleApiRequest(
this: IExecuteFunctions | ILoadOptionsFunctions,
method: IHttpRequestMethods,
resource: string,
body: any = {},
qs: IDataObject = {},
uri?: string,
headers: IDataObject = {},
): Promise<any> {
const authenticationMethod = this.getNodeParameter(
'authentication',
0,
'serviceAccount',
) as string;
const options: IRequestOptions = {
headers: {
'Content-Type': 'application/json',
},
method,
body,
qs,
uri: uri || `https://translation.googleapis.com${resource}`,
json: true,
};
try {
if (Object.keys(headers).length !== 0) {
options.headers = Object.assign({}, options.headers, headers);
}
if (Object.keys(body as IDataObject).length === 0) {
delete options.body;
}
if (authenticationMethod === 'serviceAccount') {
const credentials = await this.getCredentials('googleApi');
const { access_token } = await getGoogleAccessToken.call(this, credentials, 'translate');
options.headers!.Authorization = `Bearer ${access_token}`;
return await this.helpers.request(options);
} else {
return await this.helpers.requestOAuth2.call(this, 'googleTranslateOAuth2Api', options);
}
} catch (error) {
throw new NodeApiError(this.getNode(), error as JsonObject);
}
}
export async function googleApiRequestAllItems(
this: IExecuteFunctions | ILoadOptionsFunctions,
propertyName: string,
method: IHttpRequestMethods,
endpoint: string,
body: any = {},
query: IDataObject = {},
): Promise<any> {
const returnData: IDataObject[] = [];
let responseData;
query.maxResults = 100;
do {
responseData = await googleApiRequest.call(this, method, endpoint, body, query);
query.pageToken = responseData.nextPageToken;
returnData.push.apply(returnData, responseData[propertyName] as IDataObject[]);
} while (responseData.nextPageToken !== undefined && responseData.nextPageToken !== '');
return returnData;
}
@@ -0,0 +1,18 @@
{
"node": "n8n-nodes-base.googleTranslate",
"nodeVersion": "1.0",
"codexVersion": "1.0",
"categories": ["Utility"],
"resources": {
"credentialDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/credentials/google/oauth-single-service/"
}
],
"primaryDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.googletranslate/"
}
]
}
}
@@ -0,0 +1,220 @@
import type {
IDataObject,
IExecuteFunctions,
ILoadOptionsFunctions,
INodeExecutionData,
INodePropertyOptions,
INodeType,
INodeTypeDescription,
} from 'n8n-workflow';
import { NodeConnectionTypes } from 'n8n-workflow';
import { googleApiRequest } from './GenericFunctions';
export interface IGoogleAuthCredentials {
email: string;
privateKey: string;
}
export class GoogleTranslate implements INodeType {
description: INodeTypeDescription = {
displayName: 'Google Translate',
name: 'googleTranslate',
// eslint-disable-next-line n8n-nodes-base/node-class-description-icon-not-svg
icon: 'file:googletranslate.png',
group: ['input', 'output'],
version: [1, 2],
description: 'Translate data using Google Translate',
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
schemaPath: 'Google/Translate',
defaults: {
name: 'Google Translate',
},
usableAsTool: true,
inputs: [NodeConnectionTypes.Main],
outputs: [NodeConnectionTypes.Main],
credentials: [
{
name: 'googleApi',
required: true,
displayOptions: {
show: {
authentication: ['serviceAccount'],
},
},
},
{
name: 'googleTranslateOAuth2Api',
required: true,
displayOptions: {
show: {
authentication: ['oAuth2'],
},
},
},
],
properties: [
{
displayName: 'Authentication',
name: 'authentication',
type: 'options',
options: [
{
name: 'Service Account',
value: 'serviceAccount',
},
{
name: 'OAuth2',
value: 'oAuth2',
},
],
default: 'serviceAccount',
displayOptions: {
show: {
'@version': [1],
},
},
},
{
displayName: 'Authentication',
name: 'authentication',
type: 'options',
options: [
{
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
name: 'OAuth2 (recommended)',
value: 'oAuth2',
},
{
name: 'Service Account',
value: 'serviceAccount',
},
],
default: 'oAuth2',
displayOptions: {
show: {
'@version': [2],
},
},
},
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Language',
value: 'language',
},
],
default: 'language',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['language'],
},
},
options: [
{
name: 'Translate',
value: 'translate',
description: 'Translate data',
action: 'Translate a language',
},
],
default: 'translate',
},
// ----------------------------------
// All
// ----------------------------------
{
displayName: 'Text',
name: 'text',
type: 'string',
default: '',
description: 'The input text to translate',
required: true,
displayOptions: {
show: {
operation: ['translate'],
},
},
},
{
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-wrong-for-dynamic-options
displayName: 'Translate To',
name: 'translateTo',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getLanguages',
},
default: '',
description:
'The language to use for translation of the input text, set to one of the language codes listed in <a href="https://cloud.google.com/translate/docs/languages">Language Support</a>. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
required: true,
displayOptions: {
show: {
operation: ['translate'],
},
},
},
],
};
methods = {
loadOptions: {
async getLanguages(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = [];
const {
data: { languages },
} = await googleApiRequest.call(this, 'GET', '/language/translate/v2/languages');
for (const language of languages) {
returnData.push({
name: language.language.toUpperCase(),
value: language.language,
});
}
return returnData;
},
},
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const length = items.length;
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
const responseData: INodeExecutionData[] = [];
for (let i = 0; i < length; i++) {
if (resource === 'language') {
if (operation === 'translate') {
const text = this.getNodeParameter('text', i) as string;
const translateTo = this.getNodeParameter('translateTo', i) as string;
const response = await googleApiRequest.call(this, 'POST', '/language/translate/v2', {
q: text,
target: translateTo,
});
const [translation] = response.data.translations;
const executionData = this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray(translation as IDataObject),
{ itemData: { item: i } },
);
responseData.push(...executionData);
}
}
}
return [responseData];
}
}
@@ -0,0 +1,12 @@
{
"type": "object",
"properties": {
"detectedSourceLanguage": {
"type": "string"
},
"translatedText": {
"type": "string"
}
},
"version": 1
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB