guides
TM updates
Keep a translation memory outside wxrks in sync: each time a work unit is delivered, download as TMX the translation memory entries that work unit saved, and import them into your own system.
How it works
Every translation memory entry in wxrks remembers the work unit that last saved it. A TM updates export of a work unit holds the entries whose current translation was saved by that work unit, nothing else:
- An entry another work unit overwrote later belongs to that other work unit's export, not to this one. Each export reflects the translation memory as it is now, so exports never need to run, or be imported, in a particular order.
- You get one TMX file per translation memory. A file is empty when the work unit wrote nothing to that translation memory.
- Each entry carries its source and the target the work unit saved, with the same context as any TMX export from wxrks.
The flow for an integration is three calls, started by a webhook:
- wxrks calls your server with a
WORK_UNIT_STATUS_CHANGEevent when a work unit is delivered. - Your server calls Export Work Unit TM Updates with the event's
project_uuidandid. - It polls each job with Get Work Unit TM Update until it completes, then downloads the TMX from
downloadUrl.
Before you start
The API user that makes the calls needs, in the org unit of the projects:
PROJECT_export_import_file, to export TM updates.- Access to the project, through its org unit.
It does not need access to the translation memories themselves: the export only holds what the project's work units saved.
Create a webhook of type WORK_UNIT_STATUS_CHANGE with a secret, and turn on Enable Webhook Events in the org unit's Notifications tab. See Webhooks.
1. Receive the delivery
A WORK_UNIT_STATUS_CHANGE event is sent for every status change of a work unit. Act on the ones whose new_status is DELIVERED.
{
"id": "abd025f0-d619-4337-b25e-30e5f69822c1",
"project_uuid": "324cb7d0-a9f1-4247-a4f7-752d29dd302a",
"org_unit_uuid": "0b5e1a3c-7f0e-4c8e-9d65-2b8f3c1e4a77",
"source_locale": "en_us",
"target_locale": "pt_br",
"project_step_level": 1,
"workflow": "TRANSLATION",
"is_last_workflow": true,
"previous_status": "READY_TO_TRANSLATE",
"new_status": "DELIVERED"
}
| Field | Meaning |
|---|---|
id | The work unit. |
project_uuid | Its project. With id, all the export call needs. |
target_locale, source_locale | The language pair of the work unit. |
project_step_level, workflow, is_last_workflow | The workflow step of the work unit, and whether it is the project's last one. Sync after the last step only when you want the reviewed translations alone. |
previous_status, new_status | The status the work unit left and the one it moved to. A delivery that the client must still accept is DELIVERED_WAITING_CONFIRMATION first, and DELIVERED once accepted: sync on DELIVERED. |
The event also carries the work unit's file and word counts. Check the signature, answer 2xx within 3 seconds, then make the calls below outside the request. Store the X-BWX-Event-ID of the events you handled: a retry carries the same id.
2. Start the exports
Export Work Unit TM Updates starts one TMX export per translation memory of the project and returns the jobs:
curl -X POST "$WXRKS/api/v3/project/$PROJECT/work-unit/$WORK_UNIT/tm-updates" \
-H "X-AUTH-TOKEN: $WXRKS_TOKEN"jobs = requests.post(f"{WXRKS}/api/v3/project/{project}/work-unit/{work_unit}/tm-updates",
headers={"X-AUTH-TOKEN": token}).json()[
{ "jobId": 48213, "tmUuid": "b656c536-8464-42e7-b387-4c6499882551", "tmName": "Product UI", "status": "SCHEDULED" }
]
- The exports cover every translation memory of the project that some workflow step writes to, and any other one the work unit wrote to.
- An empty list means the project has no translation memory to export.
- A work unit that is not in the project in the path fails with
422, and a project the API user cannot reach with403.
3. Wait, then download
Get Work Unit TM Update reports one job. Poll it every few seconds:
curl "$WXRKS/api/v3/project/$PROJECT/work-unit/$WORK_UNIT/tm-updates/48213" \
-H "X-AUTH-TOKEN: $WXRKS_TOKEN"job = requests.get(f"{WXRKS}/api/v3/project/{project}/work-unit/{work_unit}/tm-updates/{job_id}",
headers={"X-AUTH-TOKEN": token}).json(){
"jobId": 48213,
"tmUuid": "b656c536-8464-42e7-b387-4c6499882551",
"status": "COMPLETED",
"translationUnits": 312,
"downloadUrl": "https://…/tm-export/…?X-Amz-Expires=3600&…",
"failureReason": null
}
status | What to do |
|---|---|
SCHEDULED | The export waits for translations still on their way to the translation memory. Keep polling. |
STARTING, STARTED | The export runs. Keep polling. |
COMPLETED | Download the TMX from downloadUrl. translationUnits says how many entries it holds; skip the import when it is 0. |
FAILED | See failureReason. With TM_WRITES_PENDING, start the export again a few minutes later; otherwise report it. |
downloadUrlis a signed link, valid for one hour after the job completed. Download the file right away; to get a new link, start the export again.- A job can be read only by the API user that started it, and only through the work unit it was started for: another one answers
403. - A job can be polled for 24 hours; after that it answers
403too. A job interrupted by a service restart endsFAILEDon its own, at the latest one hour after it started: then start the export again.
Translations still on their way
Translations reach the translation memory asynchronously, whether they were confirmed in the editor, imported from a file or confirmed in bulk. A delivery can happen while the last of them are still being written.
Each export therefore starts as SCHEDULED. A few seconds after your request, it marks what is still on its way to the translation memory, waits until all of it has been written, and only then reads the translation memory. You get every translation saved before that mark, without timing your calls.
Under a heavy load the wait can run out: after two minutes the job ends FAILED with failureReason TM_WRITES_PENDING, and starting the export again later gives the complete file.
When to sync
- On every delivery: the simplest approach. Since each export holds only the entries the work unit still owns, importing the files in any order leaves your translation memory with the latest translations.
- Continuous projects: their work units stay open and are never delivered, so no
DELIVEREDevent comes. Export their work units on your own schedule instead. - Again later: an export is always safe to repeat. Re-run it for a work unit whose segments were changed and delivered again, or when a job failed.
Reference: Export Work Unit TM Updates, Get Work Unit TM Update, Webhooks.