n8n-nodes-transglot
v0.1.0
Published
n8n community node for transglot: push source files, run AI translation, pull localized files, read project/batch status, and trigger workflows on project events over the deploy-token API.
Maintainers
Readme
n8n-nodes-transglot
An n8n community node package for transglot.
It gives you:
- transglot (action node): push source files, run AI translation, pull localized files, and read project / batch status.
- transglot Trigger (trigger node): start a workflow when a project event fires (batch completed, keys created, QA finished, …), via REST hooks.
Everything talks to your transglot install over the deploy-token API ({baseUrl}/v1/...). A deploy token is the project (deploy-key model), so there is no project id in any URL.
Installation
This is a community node. Install it from the n8n UI:
- Go to Settings → Community Nodes → Install.
- Enter the package name:
n8n-nodes-transglot. - Agree to the risk prompt and install.
Or, for a self-hosted instance, install into your n8n custom-nodes directory:
cd ~/.n8n/nodes # or your N8N_CUSTOM_EXTENSIONS path
npm install n8n-nodes-transglotThen restart n8n. See the n8n docs on installing community nodes.
Publishing is your step. This package is not published to npm / the n8n community registry by this repo. To publish it yourself: set
name,author, andrepositoryinpackage.json, runnpm run build, andnpm publish(the n8n registry indexes packages that carry then8n-community-node-packagekeyword, which this one does).
Credentials
Create a transglot API credential:
| Field | Example | Notes |
| --- | --- | --- |
| Base URL | https://api.transglot.ai | The API root, with no /api segment (removed when the API moved to its own host). All calls go under {baseUrl}/v1/.... |
| API Token | tgl_… | A project deploy token minted in the web app. Stored encrypted by n8n. |
The token is sent as Authorization: Bearer <token>. Clicking Test issues
GET {baseUrl}/v1/project. A 200 confirms the URL, token, and project without changing
anything.
A deploy token carries abilities (push / pull / manage / read / write). The
operations here need:
| Operation | Endpoint | Ability |
| --- | --- | --- |
| Project → Get | GET /v1/project | any deploy ability |
| Project → Push Source | POST /v1/push | push |
| Project → Translate | POST /v1/translate | manage |
| Project → Pull | GET /v1/pull | pull |
| Batch → Get | GET /v1/batches/{id} | any deploy ability |
| Trigger subscribe / unsubscribe | POST / DELETE /v1/webhooks | manage |
| Trigger event catalog | GET /v1/webhooks/events | any deploy ability |
Action node: transglot
Project → Get
GET /v1/project. Returns { id, name, slug, source_locale, locales[], keys_count }.
Project → Push Source
POST /v1/push as multipart/form-data. Uploads one source file (read from a binary
property on the input item) and returns the push diff
({ keys_created, keys_deleted, source_updated, translations_written, conflicts[], unknown_keys[], warnings[], batch, quota_exceeded }).
The node builds the same fields the CLI sends: file (the bytes plus a file name),
format, locale, and mode=sync_removals only when Sync Removals is on.
- Input Binary Field: the binary property holding the file to upload (default
data). Feed it from a Read/Write Files from Disk or HTTP Request node. - Format: the codec used to parse the uploaded source (same 20 formats as Pull).
- Locale: the locale the uploaded file's values are in (a configured project locale).
- File Name (Additional Fields): overrides the uploaded file name; defaults to the
binary field's own file name. A
{locale}placeholder is replaced with the Locale. - Sync Removals (Additional Fields): when on, keys absent from the file are deleted
from the project (
mode=sync_removals). Off by default so a partial file never prunes keys.
{locale}-collision guard. When one Push node processes several input items, the node
refuses to upload the same resolved file name under two different locales in a single
execution, because that would push the same file twice. Give each locale its own name (add a
{locale} placeholder to File Name, or use distinct file names). Under
Continue On Fail the collision is reported as a per-item error instead of aborting.
Project → Translate
POST /v1/translate. Starts an AI batch and returns 202 with the batch handle
({ id, status, trigger, total, completed, failed, … }). Poll it with Batch → Get.
- Scope:
missing|stale|all|selected. - Key IDs (Additional Fields): comma-separated key IDs, used with
selected(max 2000). - Locales (Additional Fields): comma-separated target locales; empty = all configured targets.
Only one AI batch may run at a time; a second call returns 409 active-batch with the
running batch_id.
Project → Pull
GET /v1/pull?format=&locale=&min_state=. Returns the serialized locale file. The node
emits { format, locale, content, parsed }, where content is the raw file body and parsed
is the JSON-decoded object when the format is JSON-shaped (json_*, flutter_arb,
laravel_json). 20 formats are supported (JSON, Android XML, iOS .strings/.xcstrings,
Flutter ARB, XLIFF 1.2 / 2.0, Gettext .po, YAML, CSV, XLSX, .properties, .resx,
Markdown, Unity CSV, Unreal .po, …).
Batch → Get
GET /v1/batches/{id}. Enable Include Failures to add include=failures and get the
per-item [{ key, locale, error }] list.
Example: read a source file from disk and push it
A minimal Read/Write Files from Disk → transglot workflow that uploads
locales/en.json as the English source:
- Read/Write Files from Disk (Read operation)
- File(s) Selector:
locales/en.json - Put Output in Field:
data
- File(s) Selector:
- transglot
- Resource:
Project - Operation:
Push Source - Input Binary Field:
data - Format:
JSON (Nested) - Locale:
en - (optional) Additional Fields → Sync Removals: on, to prune keys dropped from the file
- Resource:
To push several locales from one run, feed multiple binary items (one per file) and set
File Name to strings.{locale}.json with a per-item Locale so the uploads never
collide. Chain Batch → Get afterward to poll any translation batch the push queued
(the diff's batch field carries its id).
Trigger node: transglot Trigger
Pick an Event (loaded live from GET /v1/webhooks/events, with a static fallback):
batch.completed, batch.failed, key.created, key.updated, key.deleted,
translation.updated, translation.reviewed, language.added, glossary.updated,
qa.completed, source_drift.repaired.
Lifecycle (REST hooks):
- Activate →
POST /v1/webhookswith{ url: <n8n webhook URL>, events: [<event>] }; the returned subscriptionidis stored in the node's static data. - Deactivate / delete →
DELETE /v1/webhooks/{id}.
Each delivery is an HTTP POST whose body is emitted verbatim as the workflow item:
{
"event": "batch.completed",
"delivered_at": "2026-07-08T09:41:00+00:00",
"project": { "id": 12, "slug": "acme-web" },
"batch": { "id": 4821, "status": "completed", "trigger": "push", "total": 240, "completed": 240, "failed": 0, "language_breakdown": { "fr": 120, "de": 120 }, "started_at": "2026-07-08T09:39:13+00:00", "finished_at": "2026-07-08T09:41:00+00:00" }
}Some events coalesce (a burst of key/translation changes is debounced into one delivery
with { count, samples, window_seconds } instead of the block shown above). The event
catalog (and each event's coalesced / window_seconds contract) is what the dropdown reads.
Verifying delivery signatures (X-Transglot-Signature)
Every delivery is HMAC-signed. When you subscribe, the POST /v1/webhooks response includes
a secret once (it is never returned again). transglot signs the raw request body and
sends these headers:
| Header | Meaning |
| --- | --- |
| X-Transglot-Event | the event name |
| X-Transglot-Delivery | a unique delivery id |
| X-Transglot-Timestamp | unix seconds, part of the signed message |
| X-Transglot-Signature | sha256=<hex> |
The signature is Stripe-shaped:
signature = "sha256=" + HMAC_SHA256( key = secret, message = "{timestamp}.{rawBody}" )Recompute it with hash_equals-style constant-time comparison and reject deliveries whose
timestamp is older than ~5 minutes (replay window). n8n itself does not verify the signature
for you. If you need enforcement, capture the subscription secret (e.g. subscribe once with
the HTTP Request node, or read it from the web app) and verify in a Code node or a
reverse proxy in front of the n8n webhook URL. The trigger node emits the body as-is so a
downstream node can do this.
Development
npm install
npm run build # tsc -> dist/, then copies node icons into dist/
npm test # jest (unit tests for the trigger lifecycle + request builder)
npm run typecheck # tsc --noEmit
npm run lint # eslint (see note below)Before publishing, run the official n8n community-node linter
(@n8n/eslint-plugin-community-nodes / eslint-plugin-n8n-nodes-base). It is the canonical
gate for the n8n registry and checks node/credential/package.json conventions this local
ESLint config does not.
Full end-to-end validation (the credential Test button, the loadOptions dropdown, and the
webhook create/delete lifecycle) requires a running n8n instance pointed at a real transglot
install, because those code paths call httpRequestWithAuthentication / getNodeWebhookUrl, which
only exist inside the n8n runtime. The jest suite mocks that surface to assert the exact
requests the node builds.
License
MIT
