{"id":107,"date":"2026-09-23T11:24:45","date_gmt":"2026-09-23T11:24:45","guid":{"rendered":"https:\/\/docs.latw.ai\/uncategorized\/translation-prompt-2\/"},"modified":"2026-09-23T11:24:45","modified_gmt":"2026-09-23T11:24:45","slug":"translation-prompt-2","status":"publish","type":"post","link":"https:\/\/docs.latw.ai\/pl\/latw-for-polylang\/translation-prompt-2\/","title":{"rendered":"How the Translation Prompt Works"},"content":{"rendered":"<p><em>Editing the prompt is available in LATW AI Translation for Polylang <strong>PRO<\/strong>.<\/em><\/p>\n<p>The prompt is the instruction sent to a language model with every translation: what it is<br \/>\ntranslating, into what, and how it should behave. The free plugin ships one prompt and prints it in<br \/>\nfull under <strong>AI Translation \u2192 Settings \u2192 Translation \u2192 Translation Prompt<\/strong> \u2014 so you always know<br \/>\nexactly what is being sent, even where there is nothing to change.<\/p>\n<p>With PRO that text becomes an editable field, with a <strong>Reset to Default<\/strong> button next to it. Your<br \/>\nwording is stored by PRO, so it is still there if a licence lapses and comes back; while the<br \/>\nlicence is inactive, translations use the prompt the free plugin ships.<\/p>\n<h2>What the AI actually receives<\/h2>\n<p>A page does not reach the AI as a page. The plugin splits it into separate <strong>fields<\/strong> \u2014 the title,<br \/>\nthe excerpt, each piece of text in the block content, each Elementor text field, every translated<br \/>\ncustom field \u2014 and sends those fields as one JSON object:<\/p>\n<pre><code class=\"language-json\">{\n  \"post_title\": \"Aeropress filters compared\",\n  \"content_1\": \"Paper, metal or cloth?\",\n  \"content_2\": \"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 place in<br \/>\nthe post it came from, HTML and shortcodes survive untouched inside the values, and a broken answer<br \/>\nis 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 placeholders filled in\n2. Website context           your Website Description, via {{website_context}}\n3. Glossary                  the pairs for this language pair, via {{glossary}}\n4. Payload 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 placeholders<\/h2>\n<p>The template ships with a default that tells the model to behave as a translation engine (no<br \/>\nquestions, no commentary, no splitting the answer into parts) and to return JSON with the same keys<br \/>\nas the input.<\/p>\n<p>Four placeholders are filled in when the prompt is built:<\/p>\n<table>\n<thead>\n<tr>\n<th>Placeholder<\/th>\n<th>Filled with<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>{{source_language}}<\/code><\/td>\n<td>The language name of the original, e.g. &#8220;Polish&#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 <strong>Website Description<\/strong> from Settings \u2192 General, prefixed with &#8220;Website context:&#8221;, if you wrote one<\/td>\n<\/tr>\n<tr>\n<td><code>{{glossary}}<\/code><\/td>\n<td>Your glossary entries for this language pair <em>(PRO)<\/em><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>A placeholder that is not in the template is not sent.<\/strong> This matters most for the glossary: if<br \/>\nyou edit the prompt and remove <code>{{glossary}}<\/code>, translations continue perfectly happily with no<br \/>\nglossary at all, and nothing in the result would say so. The settings screen therefore warns about<br \/>\nevery missing placeholder \u2014 as you type, and again after saving \u2014 and says what each one costs you:<br \/>\nwithout <code>{{destination_language}}<\/code>, for instance, the model is not told which language to translate<br \/>\ninto at all.<\/p>\n<p><code>{{glossary}}<\/code> resolves to nothing without the PRO add-on, so a prompt that mentions it still works<br \/>\nin the free version \u2014 the line simply disappears.<\/p>\n<p>Keep the placeholders. A prompt with <code>{{destination_language}}<\/code> removed leaves the model guessing<br \/>\nwhich language you wanted. <strong>Reset to Default<\/strong> restores the shipped template.<\/p>\n<h2>Part 4 \u2014 the payload 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 wrong translates each<br \/>\nvalue in isolation, and the result reads as if written by several people.<\/p>\n<p>So the plugin appends a short note saying what the payload is. It is a fact about the job, not a<br \/>\npreference, so it is added to your custom prompt as well as to the default one. There are three<br \/>\nversions:<\/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>The values are fields of a single web page and belong together: keep terminology consistent across all of them, and translate the title in the register a page title would use.<\/td>\n<\/tr>\n<tr>\n<td>A taxonomy term<\/td>\n<td>The values are term names and descriptions: translate them as short labels, not as prose, as brief as the original.<\/td>\n<\/tr>\n<tr>\n<td>Interface strings<\/td>\n<td>The values are unrelated interface strings \u2014 buttons, menu items, notices: each is independent, keep it close to the original in length, and keep placeholder tokens such as <code>%s<\/code> exactly as they are.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Part 5 \u2014 the REFERENCE block<\/h2>\n<p><em>PRO.<\/em> This appears only in the <strong>Translate only changed strings, with the whole page as context<\/strong><br \/>\nmode (<em>Updating Outdated Translations<\/em>). The job translates the changed fields alone, and the<br \/>\nuntouched rest of the page travels with it as reference:<\/p>\n<pre><code class=\"language-json\">[\n  {\n    \"field\": \"post_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 must<br \/>\nnot translate or return any of it. Only the fields in INPUT JSON are asked for, and a field from<br \/>\nREFERENCE that comes back anyway is not written: the published translation stays.<\/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>Passes the result to the <code>latwaitp_translated_strings<\/code> filter, where your site can correct or<br \/>\nreject it \u2014 see <em>Checking Translations Before They Are Saved<\/em>.<\/li>\n<li>Rebuilds the translated post from the structure of the original, putting each translated value<br \/>\nback where its field came from, and saves it in Polylang.<\/li>\n<\/ol>\n<p>A reply that is not valid JSON fails the job instead of saving half a page.<\/p>\n<h2>The other settings that shape the request<\/h2>\n<ul>\n<li><strong>Website Description<\/strong> (Settings \u2192 General) \u2014 if all you want is for the model to understand what<br \/>\nkind of site it is translating, you do not need an editable prompt at all. It is sent with every<br \/>\ntranslation in the free version too, and for most sites it is the difference that matters.<\/li>\n<li><strong>Reasoning Effort<\/strong> (Settings \u2192 General) is sent alongside the prompt on models that support it.<br \/>\nHigher effort means slower and more expensive, with more attention paid to instructions like the<br \/>\nglossary.<\/li>\n<li><strong>Processing<\/strong> (Settings \u2192 General) changes how the request is delivered, never what it contains.<\/li>\n<li><strong>Google Translate, DeepL and MyMemory ignore this page entirely.<\/strong> They are machine-translation<br \/>\nengines: they translate text and cannot follow instructions, so the prompt, the website<br \/>\ndescription, the payload note and the REFERENCE block do not apply. The glossary still reaches<br \/>\nDeepL, through its own glossary feature \u2014 see <em>Translation Engine &#8211; AI Providers<\/em>.<\/li>\n<\/ul>\n<h2>Seeing what was actually sent<\/h2>\n<p><strong>AI Translation \u2192 History<\/strong> has a <strong>Request<\/strong> column. For OpenAI in background or batch processing,<br \/>\nand for Claude in batch processing, <strong>View<\/strong> shows the exact prompt that was sent, with the<br \/>\nplaceholders filled in and the payload note and REFERENCE block included. For synchronous jobs it<br \/>\nshows the fields that were sent.<\/p>\n<p>This is the fastest way to settle questions like &#8220;was my glossary in there?&#8221; \u2014 it either appears in<br \/>\nthe stored prompt or it does not.<\/p>\n<h2>Editing the prompt safely<\/h2>\n<p>Worth adding:<\/p>\n<ul>\n<li>Tone and register \u2014 formal or informal address, which matters a great deal in German, Polish or<br \/>\nFrench.<\/li>\n<li>Vocabulary specific to your industry \u2014 &#8220;this is a medical site, prefer clinical terms over<br \/>\ncolloquial ones&#8221;.<\/li>\n<li>Things that should stay in the original language \u2014 product names, legal terms, code samples.<\/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 the post; a prompt that<br \/>\ninvites prose instead of JSON fails every job. Rewriting that section will not make translations<br \/>\nbetter.<\/li>\n<li>The four placeholders, even if you rewrite everything around them.<\/li>\n<li>The instruction not to split the answer into parts.<\/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 filter described in <em>Checking Translations<br \/>\nBefore They Are Saved<\/em>.<\/li>\n<\/ul>\n<h2>What happens if the licence lapses<\/h2>\n<p>The site goes back to translating with the prompt the free plugin ships. Your own wording is not<br \/>\ndeleted \u2014 it is stored and comes back if the licence does \u2014 but it is not used while the prompt is<br \/>\nlocked. This is deliberate: a prompt nobody can see or edit should not keep steering translations.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Editing the prompt is available in LATW AI Translation for Polylang PRO. The prompt is the instruction sent to a language model with every translation: what\u2026<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_latwm_translated_slug":"","footnotes":""},"categories":[17],"tags":[],"class_list":["post-107","post","type-post","status-publish","format-standard","hentry","category-latw-for-polylang"],"_links":{"self":[{"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/posts\/107","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=107"}],"version-history":[{"count":0,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/posts\/107\/revisions"}],"wp:attachment":[{"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/media?parent=107"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/categories?post=107"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/docs.latw.ai\/pl\/wp-json\/wp\/v2\/tags?post=107"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}