{"id":64,"date":"2026-09-18T10:57:44","date_gmt":"2026-09-18T10:57:44","guid":{"rendered":"https:\/\/docs.latw.ai\/uncategorized\/translation-prompt\/"},"modified":"2026-09-18T10:57:44","modified_gmt":"2026-09-18T10:57:44","slug":"translation-prompt","status":"publish","type":"post","link":"https:\/\/docs.latw.ai\/pl\/latw-for-wpml\/translation-prompt\/","title":{"rendered":"How the Translation Prompt Works"},"content":{"rendered":"<p><em>Available in LATW AI Translator for WPML <strong>PRO<\/strong> (version 2.3.0 and later).<\/em><\/p>\n<h2>What the AI actually receives<\/h2>\n<p>A page does not reach the AI as a page. WPML hands the plugin a translation job made of separate<br \/>\n<strong>fields<\/strong> \u2014 the title, the excerpt, each paragraph or heading of block content, every custom<br \/>\nfield \u2014 and the plugin sends those fields as one JSON object, keyed by the field name:<\/p>\n<pre><code class=\"language-json\">{\n  \"title\": \"Aeropress filters compared\",\n  \"field-intro\": \"Paper, metal or cloth?\",\n  \"body\": \"The paper filter keeps roughly half the sediment out of the glass.\"\n}<\/code><\/pre>\n<p>JSON rather than plain text, for three reasons: the answer can be mapped back to the exact WPML<br \/>\nfield it came from, HTML and shortcodes survive untouched inside the values, and a truncated<br \/>\nanswer is detectable instead of being silently saved.<\/p>\n<p>Around that JSON the plugin assembles the prompt. Every translation is sent in this shape:<\/p>\n<pre><code>1. Translation prompt        the template from Settings, with its variables filled in\n2. Website context           your Website Description, via {{website_context}}\n3. Glossary                  the pairs for this language pair, via {{glossary}}\n4. CONTEXT note              added by the plugin \u2014 what this payload is\n5. REFERENCE                 added by the plugin \u2014 the rest of the page (one mode only)\n6. INPUT JSON                the fields to translate<\/code><\/pre>\n<p>Parts 1\u20133 are yours to edit. Parts 4\u20136 are assembled per job and cannot be edited, because they<br \/>\ndescribe the job rather than your preferences.<\/p>\n<h2>Part 1 \u2014 the template and its variables<\/h2>\n<p><strong>Settings \u2192 Translation \u2192 Translation Prompt<\/strong> holds the instruction text. It ships with a<br \/>\ndefault that tells the model to behave as a translation engine (no questions, no commentary, no<br \/>\nsplitting the answer into parts) and to return JSON with the same keys as the input.<\/p>\n<p>Four variables are substituted when the prompt is built:<\/p>\n<table>\n<thead>\n<tr>\n<th>Variable<\/th>\n<th>Replaced with<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>{{source_language}}<\/code><\/td>\n<td>The language name the content is in, e.g. &#8220;English&#8221;.<\/td>\n<\/tr>\n<tr>\n<td><code>{{destination_language}}<\/code><\/td>\n<td>The language name being translated into, e.g. &#8220;German&#8221;.<\/td>\n<\/tr>\n<tr>\n<td><code>{{website_context}}<\/code><\/td>\n<td>Your Website Description, prefixed with &#8220;Website context:&#8221;.<\/td>\n<\/tr>\n<tr>\n<td><code>{{glossary}}<\/code><\/td>\n<td>The glossary pairs that apply to this language pair, one per line.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>A variable that is not in the template is not sent.<\/strong> This matters most for the glossary: if you<br \/>\nedit the prompt and remove <code>{{glossary}}<\/code>, translations continue perfectly happily with no<br \/>\nglossary at all, and nothing in the result says so. The settings screen therefore warns about<br \/>\nevery missing variable, as you type and after saving. <strong>Reset to Default<\/strong> restores the shipped<br \/>\ntemplate.<\/p>\n<p>The glossary block is only as strong as the model&#8217;s willingness to follow it. It says &#8220;use this<br \/>\ntranslation for this term&#8221;; it cannot say &#8220;never use that word&#8221;. For that, see <em>Checking<br \/>\nTranslations Before They Are Saved<\/em>.<\/p>\n<h2>Part 4 \u2014 the CONTEXT note<\/h2>\n<p>The JSON above is ambiguous in a way that matters: three separate values could be three fragments<br \/>\nof one article, or three unrelated interface strings. A model that guesses &#8220;unrelated fragments&#8221;<br \/>\ntranslates each value in isolation, and the result is the symptom sites report as <em>the translation<br \/>\nsounds mechanical, as if it were written by several people<\/em> \u2014 terminology that drifts between<br \/>\nparagraphs, a heading that no longer matches the text under it, formality that changes halfway<br \/>\ndown the page.<\/p>\n<p>So the plugin appends a short note saying what the payload is. It is not a preference, it is a<br \/>\nfact about the job, so it is added to your custom prompt as well as to the default one. There are<br \/>\nthree versions:<\/p>\n<table>\n<thead>\n<tr>\n<th>Payload<\/th>\n<th>What the note says<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>A post or page<\/td>\n<td>Everything in the JSON is <strong>one page<\/strong>, 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.<\/td>\n<\/tr>\n<tr>\n<td>A taxonomy term<\/td>\n<td>The JSON is one term \u2014 its name and its description \u2014 to be translated as one unit.<\/td>\n<\/tr>\n<tr>\n<td>A String Translation batch<\/td>\n<td>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.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The distinction is the point. Telling the model that a batch of button labels is &#8220;one page&#8221; would<br \/>\nbe worse than saying nothing at all.<\/p>\n<h2>Part 5 \u2014 the REFERENCE block<\/h2>\n<p>This appears only in the <strong>Translate only changed strings, with the whole page as context<\/strong><br \/>\noutdated mode (<em>Updating Outdated Translations<\/em>). The job translates the changed fields alone, and<br \/>\nthe untouched rest of the page travels with it as reference:<\/p>\n<pre><code class=\"language-json\">[\n  {\n    \"field\": \"title\",\n    \"source\": \"Aeropress filters compared\",\n    \"published_translation\": \"Aeropress-Filter im Vergleich\"\n  }\n]<\/code><\/pre>\n<p>The note above it tells the model that this material is approved \u2014 it may contain corrections a<br \/>\nhuman made by hand \u2014 so it must reuse that terminology and tone rather than improve on it, and<br \/>\nmust not translate or return any of it. Only the fields in INPUT JSON come back and only they are<br \/>\nwritten.<\/p>\n<h2>What comes back<\/h2>\n<p>The model returns a JSON object with the same keys. The plugin then:<\/p>\n<ol>\n<li>Parses it, tolerating a model that wraps the JSON in a markdown fence.<\/li>\n<li>Matches each key to the WPML field it came from. A key that was never sent has nowhere to go<br \/>\nand is dropped.<\/li>\n<li>Passes the result to the <code>latwaitrp_translated_strings<\/code> filter, where your site can correct or<br \/>\nreject it \u2014 this is the only point where anything looks at the <em>content<\/em> of a translation.<\/li>\n<li>Hands the fields to WPML, which rebuilds the translated post.<\/li>\n<\/ol>\n<p>A reply that is not valid JSON, or that arrives truncated, fails the job instead of saving half a<br \/>\npage. Failed jobs are retried up to three times &#8211; unless the provider rejected the request itself<br \/>\n(an unknown model, a setting it does not accept, a bad key), which no amount of retrying would fix.<br \/>\nThose stop at the first attempt and show the provider&#8217;s own reason.<\/p>\n<h2>The other settings that shape the request<\/h2>\n<ul>\n<li><strong>Reasoning effort<\/strong> (Settings \u2192 General) is sent alongside the prompt on models that<br \/>\nsupport it. Higher effort means slower and more expensive, with more attention paid to<br \/>\ninstructions like the glossary.<\/li>\n<li><strong>Processing mode<\/strong> (synchronous, batch, background) changes how the request is delivered, never<br \/>\nwhat it contains \u2014 the prompt is identical in all three.<\/li>\n<li><strong>DeepL and Google Translate ignore this page entirely.<\/strong> They are machine-translation engines:<br \/>\nthey translate text and cannot follow instructions, so the prompt, the website description, the<br \/>\nCONTEXT note and the REFERENCE block do not apply. DeepL still honours the glossary, natively.<\/li>\n<\/ul>\n<h2>Seeing the prompt that was actually sent<\/h2>\n<p>Every queue row stores the exact prompt in its <code>request_data<\/code> column, including the filled-in<br \/>\nvariables, the CONTEXT note and the REFERENCE block. This is the fastest way to settle questions<br \/>\nlike &#8220;was my glossary in there?&#8221; \u2014 it either appears in the stored prompt or it does not.<\/p>\n<p>The plugin log (<strong>AI Translator \u2192 Logs<\/strong>) records the job around it: the model, the mode, the<br \/>\nfields sent and, for context mode, how many fields travelled as reference.<\/p>\n<h2>Editing the prompt safely<\/h2>\n<p>Worth adding:<\/p>\n<ul>\n<li>Style and register rules \u2014 how to address the reader, which variety of a language to use,<br \/>\nwhether to keep product names in English.<\/li>\n<li>Domain instructions \u2014 &#8220;this is a medical site, prefer clinical terms over colloquial ones&#8221;.<\/li>\n<li>Things the glossary cannot express, e.g. &#8220;translate headings as noun phrases, not sentences&#8221;.<\/li>\n<\/ul>\n<p>Worth keeping:<\/p>\n<ul>\n<li>The JSON output rules. They are what makes the answer mappable back to WPML; a prompt that<br \/>\ninvites prose instead of JSON fails every job.<\/li>\n<li>The four variables, even if you rewrite everything around them.<\/li>\n<li>The instruction not to split the answer into parts. A model that answers &#8220;here is the first<br \/>\nhalf\u2026&#8221; produces an unusable job.<\/li>\n<\/ul>\n<p>Not worth relying on:<\/p>\n<ul>\n<li>The prompt alone for terminology a model keeps getting wrong. Instructions raise the odds; they<br \/>\ndo not enforce anything. Enforcement belongs in the pre-save filter described in <em>Checking<br \/>\nTranslations Before They Are Saved<\/em>.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>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\u2026<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_latwm_translated_slug":"","footnotes":""},"categories":[3],"tags":[],"class_list":["post-64","post","type-post","status-publish","format-standard","hentry","category-latw-for-wpml"],"_links":{"self":[{"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/posts\/64","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/comments?post=64"}],"version-history":[{"count":2,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/posts\/64\/revisions"}],"predecessor-version":[{"id":89,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/posts\/64\/revisions\/89"}],"wp:attachment":[{"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/media?parent=64"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/categories?post=64"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/tags?post=64"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}