Skip to content

How the Translation Prompt Works

On this page

Available in LATW AI Translator for WPML PRO (version 2.3.0 and later).

#What the AI actually receives

A page does not reach the AI as a page. WPML hands the plugin a translation job made of separate
fields — the title, the excerpt, each paragraph or heading of block content, every custom
field — and the plugin sends those fields as one JSON object, keyed by the field name:

{
  "title": "Aeropress filters compared",
  "field-intro": "Paper, metal or cloth?",
  "body": "The paper filter keeps roughly half the sediment out of the glass."
}

JSON rather than plain text, for three reasons: the answer can be mapped back to the exact WPML
field it came from, HTML and shortcodes survive untouched inside the values, and a truncated
answer is detectable instead of being silently saved.

Around that JSON the plugin assembles the prompt. Every translation is sent in this shape:

1. Translation prompt        the template from Settings, with its variables filled in
2. Website context           your Website Description, via {{website_context}}
3. Glossary                  the pairs for this language pair, via {{glossary}}
4. CONTEXT note              added by the plugin — what this payload is
5. REFERENCE                 added by the plugin — the rest of the page (one mode only)
6. INPUT JSON                the fields to translate

Parts 1–3 are yours to edit. Parts 4–6 are assembled per job and cannot be edited, because they
describe the job rather than your preferences.

#Part 1 — the template and its variables

Settings → Translation → Translation Prompt holds the instruction text. It ships with a
default that tells the model to behave as a translation engine (no questions, no commentary, no
splitting the answer into parts) and to return JSON with the same keys as the input.

Four variables are substituted when the prompt is built:

Variable Replaced with
{{source_language}} The language name the content is in, e.g. “English”.
{{destination_language}} The language name being translated into, e.g. “German”.
{{website_context}} Your Website Description, prefixed with “Website context:”.
{{glossary}} The glossary pairs that apply to this language pair, one per line.

A variable that is not in the template is not sent. This matters most for the glossary: if you
edit the prompt and remove {{glossary}}, translations continue perfectly happily with no
glossary at all, and nothing in the result says so. The settings screen therefore warns about
every missing variable, as you type and after saving. Reset to Default restores the shipped
template.

The glossary block is only as strong as the model’s willingness to follow it. It says “use this
translation for this term”; it cannot say “never use that word”. For that, see Checking
Translations Before They Are Saved
.

#Part 4 — the CONTEXT note

The JSON above is ambiguous in a way that matters: three separate values could be three fragments
of one article, or three unrelated interface strings. A model that guesses “unrelated fragments”
translates each value in isolation, and the result is the symptom sites report as the translation
sounds mechanical, as if it were written by several people
— terminology that drifts between
paragraphs, a heading that no longer matches the text under it, formality that changes halfway
down the page.

So the plugin appends a short note saying what the payload is. It is not a preference, it is a
fact about the job, so it is added to your custom prompt as well as to the default one. There are
three versions:

Payload What the note says
A post or page Everything in the JSON is one page, split into fields by the CMS. Read all of it first, translate it as one continuous document, keep terminology, tone, register and formality identical across fields, and treat a heading and the text below it as the same text.
A taxonomy term The JSON is one term — its name and its description — to be translated as one unit.
A String Translation batch The JSON holds interface strings that really are independent of each other: keep terminology and tone consistent, keep each translation about as short as its source, and do not read them as continuous prose.

The distinction is the point. Telling the model that a batch of button labels is “one page” would
be worse than saying nothing at all.

#Part 5 — the REFERENCE block

This appears only in the Translate only changed strings, with the whole page as context
outdated mode (Updating Outdated Translations). The job translates the changed fields alone, and
the untouched rest of the page travels with it as reference:

[
  {
    "field": "title",
    "source": "Aeropress filters compared",
    "published_translation": "Aeropress-Filter im Vergleich"
  }
]

The note above it tells the model that this material is approved — it may contain corrections a
human made by hand — so it must reuse that terminology and tone rather than improve on it, and
must not translate or return any of it. Only the fields in INPUT JSON come back and only they are
written.

#What comes back

The model returns a JSON object with the same keys. The plugin then:

  1. Parses it, tolerating a model that wraps the JSON in a markdown fence.
  2. Matches each key to the WPML field it came from. A key that was never sent has nowhere to go
    and is dropped.
  3. Passes the result to the latwaitrp_translated_strings filter, where your site can correct or
    reject it — this is the only point where anything looks at the content of a translation.
  4. Hands the fields to WPML, which rebuilds the translated post.

A reply that is not valid JSON, or that arrives truncated, fails the job instead of saving half a
page. Failed jobs are retried up to three times – unless the provider rejected the request itself
(an unknown model, a setting it does not accept, a bad key), which no amount of retrying would fix.
Those stop at the first attempt and show the provider’s own reason.

#The other settings that shape the request

  • Reasoning effort (Settings → General) is sent alongside the prompt on models that
    support it. Higher effort means slower and more expensive, with more attention paid to
    instructions like the glossary.
  • Processing mode (synchronous, batch, background) changes how the request is delivered, never
    what it contains — the prompt is identical in all three.
  • DeepL and Google Translate ignore this page entirely. They are machine-translation engines:
    they translate text and cannot follow instructions, so the prompt, the website description, the
    CONTEXT note and the REFERENCE block do not apply. DeepL still honours the glossary, natively.

#Seeing the prompt that was actually sent

Every queue row stores the exact prompt in its request_data column, including the filled-in
variables, the CONTEXT note and the REFERENCE block. This is the fastest way to settle questions
like “was my glossary in there?” — it either appears in the stored prompt or it does not.

The plugin log (AI Translator → Logs) records the job around it: the model, the mode, the
fields sent and, for context mode, how many fields travelled as reference.

#Editing the prompt safely

Worth adding:

  • Style and register rules — how to address the reader, which variety of a language to use,
    whether to keep product names in English.
  • Domain instructions — “this is a medical site, prefer clinical terms over colloquial ones”.
  • Things the glossary cannot express, e.g. “translate headings as noun phrases, not sentences”.

Worth keeping:

  • The JSON output rules. They are what makes the answer mappable back to WPML; a prompt that
    invites prose instead of JSON fails every job.
  • The four variables, even if you rewrite everything around them.
  • The instruction not to split the answer into parts. A model that answers “here is the first
    half…” produces an unusable job.

Not worth relying on:

  • The prompt alone for terminology a model keeps getting wrong. Instructions raise the odds; they
    do not enforce anything. Enforcement belongs in the pre-save filter described in Checking
    Translations Before They Are Saved
    .