Read Frog

How a Request Is Assembled

The order in which Read Frog builds the prompt it sends, and what it does with the text the model sends back.

Your two prompt fields are not what leaves the browser. Read Frog adds rule blocks, substitutes variables, attaches glossary terms, and then does a fair amount of work on the reply before any of it reaches the page. This page walks through both halves, in order.

Everything here is about LLM providers. Google Translate, Microsoft Translator and DeepL receive no prompt and none of these stages apply to them.

Building the request

1. Choose the paragraphs

The content script collects paragraphs as they approach the viewport, drops the ones a skip rule or the small-paragraph filter excludes, and hands the rest to a queue. On an LLM provider the queue groups compatible paragraphs into one request — same provider, same language pair, same page context — up to the character and paragraph limits on the Request Control page. That group is what becomes {{input}}.

2. Pick the prompt

Read Frog looks up the prompt id you selected. If it names a built-in, the built-in wins; otherwise it looks through your own prompts; if neither matches — a prompt you deleted while it was selected, for instance — it falls back to Default rather than failing.

3. Append the rule blocks

Extra instructions are appended to the system prompt, and only when they are needed. This is why the same prompt produces a different request on different paragraphs.

BlockAppended when
Multi-paragraph rulesThe request carries more than one paragraph
Already-translated ruleThe request carries more than one paragraph, page translation only
Protected HTML marker rulesThe text contains a data-rf-attr marker
Protected placeholder rulesThe text contains a numbered formula placeholder

A single-paragraph request gets none of them. Subtitle translation gets the multi-paragraph rules but never the already-translated rule.

4. Substitute the variables

Now the {{...}} names are replaced, in both fields, with the values described on Prompt Variables. Only the known names are replaced; anything else is left as written.

5. Attach the glossary

Last, the terms from your glossary that actually occur in this text are appended to the system prompt. They come last on purpose: a term is text you typed, and if it were attached before substitution a term that happened to contain a variable name could rewrite the prompt around it.

A finished request

Two paragraphs from an English article, translating into Simplified Chinese, on the Default prompt with AI Smart Context off. The system prompt that goes out:

You are a professional Simplified Mandarin Chinese native translator who needs to fluently translate text into Simplified Mandarin Chinese.

## Translation Rules
1. Output only the translated content, without explanations or additional content ...
2. The returned translation must maintain exactly the same number of paragraphs and format as the original text.
3. If the text contains HTML tags, consider where the tags should be placed in the translation while maintaining fluency.
4. For content that should not be translated (such as proper nouns, code, etc.), keep the original text.

## Document Metadata for Context Awareness
Webpage title: Why your timestamps are eight hours off — devblog
Webpage summary: No summary available

## Multi-paragraph Translation Rules
1. If input contains a standalone line containing only %%, use a standalone %% line in your output ...
2. **CRITICAL**: Treat %% as a separator only when it appears on its own line ...

## OUTPUT FORMAT:
- **Single paragraph input** → Output translation directly (no separators, no extra text)
- **Multi-paragraph input** → Put %% on its own line between translations

## Already-translated Input Rule
Output only {{NO_TRANSLATION_NEEDED}} when only non-translatable names, brands, handles, URLs, numbers, or code differ from Simplified Mandarin Chinese. A foreign-language phrase or clause must be translated.

And the prompt:

Translate to Simplified Mandarin Chinese:


Every timestamp you store without a zone is a bug waiting for a plane ticket.

%%

The fix is boring: store UTC, render local, and never let the two meet in a database column.

Note the two blank lines after the colon — they come from the prompt field itself, which is Translate to {{targetLanguage}}: followed by two blank lines and {{input}}.

Reading the reply

1. Trim and split

The reply is trimmed, then split on lines that contain nothing but %%. Each piece is trimmed again and lines up with the paragraph that sat in the same position of the request. A %% inside a sentence, a code sample or a quotation is not a separator — only a line that holds nothing else.

2. Check the count

Read Frog expects exactly as many pieces as it sent. A mismatch is a hard failure of the whole group, not a partial success: the request is retried up to three times with a growing delay, and if it still does not line up, every paragraph in the group is re-sent on its own. That is slower and costs more, which is why a prompt that encourages commentary or merged paragraphs is expensive rather than merely untidy.

3. Resolve "nothing to translate"

{{NO_TRANSLATION_NEEDED}} is the answer the model is told to give for a paragraph already written in your target language. When a piece is exactly that marker, Read Frog treats the translation as empty, and an empty translation renders nothing — in bilingual mode no second line appears under that paragraph, and in translation-only mode the original stays visible.

The marker is stored in the cache as-is, so a paragraph settled this way is not re-sent on the next visit. It is deliberately shaped like a variable: variable substitution only replaces the names it knows, so the marker survives prompt assembly untouched and reaches the model spelled the same way every time.

4. Discard a translation that says nothing

A model handed same-language text often echoes it back with cosmetic differences instead of using the marker — reflowed spaces, straight quotes turned curly, full-width punctuation. Read Frog compares the reply with the source after folding those differences away, and if they match it treats the result as empty too. This is why some paragraphs on a mixed-language page show no translation even though a request was made for them.

5. Verify the markers

If the text carried data-rf-attr markers, the reply must return each one exactly once, on the same kind of element. A marker that is missing, duplicated, invented or moved to a different tag fails that paragraph rather than rendering a link pointing somewhere else.

Numbered formula placeholders are checked more gently. A reply that loses or duplicates one is still shown — the missing formulas are appended — but it is not written to the cache, so the next visit gets a fresh attempt instead of a permanently degraded paragraph.

6. Store it

What survives is written to the translation cache, and the page is updated.

The cache key

A cached translation is keyed on, among other things, the finished system prompt and the finished prompt — after the rule blocks, after substitution, after the glossary.

That has three consequences worth knowing:

  • Editing a prompt orphans every translation made with the old one. Pages you have already read will be translated, and paid for, again.
  • Changing your glossary orphans only the paragraphs that contained a matched term. A paragraph that matched nothing produces a prompt byte-for-byte identical to having no glossary at all, so its cache entry survives.
  • Turning AI Smart Context on or off changes every key, because the summary variable changes — from a real summary to No summary available or back.

Clearing the cache from Options → Translation removes stored translations and page summaries. It does not touch your prompts, providers or glossaries.

On this page