プロンプト変数
Read Frog のプロンプトで使えるすべての変数と、それぞれが実際に置き換わる値。
変数は {{name}} の形で書きます。リクエストを送る直前に、Read Frog は既知の変数をそれぞれ文字列に置き換えます。それ以外は一切触りません。{{url}} のような知らない名前は、{{url}} という文字のままプロンプトに残ります。
以下の例はすべて同じページから採ったものです。https://devblog.example.com/posts/timestamps にある英語の記事を、簡体字中国語に翻訳しています。
どの変数がどこで使えるか
| 変数 | ページプロンプト | 字幕プロンプト |
|---|---|---|
{{targetLanguage}} | 使える | 使える |
{{input}} | 使える | 使える |
{{webTitle}} | 使える | 使える |
{{webDescription}} | 使える | 使える |
{{webContent}} | 使える | — |
{{webSummary}} | 使える | — |
{{videoSummary}} | — | 使える |
ページプロンプトで {{videoSummary}} を使っても、字幕プロンプトで {{webContent}} を使っても、残るのは文字そのものです。各欄の下にある変数ボタンは、その一覧が値を埋められるものだけを出します。
{{targetLanguage}}
翻訳先の言語の英語名です。言語コードではなく、インターフェースの言語に合わせて訳されることもありません。
Simplified Mandarin Chineseほかの例:English、Traditional Mandarin Chinese、Japanese、Spanish。つまり Translate to {{targetLanguage}}: と書いたプロンプトは、Translate to Simplified Mandarin Chinese: として届きます。
{{input}}
翻訳するテキストです。プロンプトがこれなしでは成り立たない、唯一の変数です。
1 段落ずつ — 前後の空白は削られ、見えない文字は取り除かれます。
Every timestamp you store without a zone is a bug waiting for a plane ticket.まとめて複数段落。LLM プロバイダーでバッチ翻訳を有効にしているときに実際に起きることです。段落は %% だけの行でつながれ、その両側に空行が 1 つずつ入ります。
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.
%%
Ordering by a naive timestamp works until the clocks change, and then it works wrongly.モデルには、同じ順番で同じ数の段落を、同じ区切り方で返すことが期待されます。Read Frog はその %% の行で返答を切り分けます。プロンプトを書き換えて区切りを変えたり、段落に番号を付けさせたり、段落を統合させたりすると、分割は失敗し、そのバッチは再試行されたうえで 1 段落ずつ再送されます。
HTML があるとき。段落にインラインのマークアップが含まれる場合です。残さなければならない属性は取り出され、要素には data-rf-attr の印が付くので、モデルには URL ではなく目印が見えます。
The fix is <a data-rf-attr="0">boring</a>: store <code data-rf-attr="1">UTC</code>, render local.数式やインラインの記号があるとき。番号付きのプレースホルダーに置き換えられ、翻訳が返ってきたあとで元の要素が複製されて戻されます。
Converting is just {{0}}, which is why nobody gets it wrong twice.プロンプトを書いているときに、この 2
つの形を目にすることはあまりありません。ただ、リクエストに余分なルールブロックが現れる理由はこれです。Read
Frog が data-rf-attr
と番号付きプレースホルダーについての指示を付けるのは、送るテキストに実際にそれが含まれているときだけです。
{{webTitle}}
ページの <title> です。ブラウザーのタブに表示されているものと同じです。
Why your timestamps are eight hours off — devblog字幕 プロンプトでは、こちらは動画のタイトルになります。
{{webDescription}}
ページ自身が持っている説明文です。<meta name="description">、<meta property="og:description">、<meta name="twitter:description"> のうち、内容がある最初のものを取ります。
A short tour of the three places a naive timestamp can go wrong, and the one rule that prevents all three.字幕 プロンプトでは、こちらは動画の説明になります。
{{webContent}}
ページの本文です。Markdown として抽出し、先頭 2000 文字 で切ります。ナビゲーション、サイドバー、フッターは落とされます。組み込みプロンプトはどれもこれを使っていません。タイトルだけでは足りないプロンプトのために用意されています。
# Why your timestamps are eight hours off
Every timestamp you store without a zone is a bug waiting for a plane ticket.
It works on your laptop, it works in CI, and it fails the first time somebody
in another country opens the report.
## Three places it goes wrong
1. **At the boundary.** A form posts `2026-03-14 09:00` and the server decides
what that means.
2. **In the column.** `timestamp without time zone` is not a moment in time; it
is a picture of a wall clock.
3. **On the way out.** Formatting in UTC and labelling it local is the same bug
wearing a hat.
The fix is boring: store UTC, render local, and never let the tw切り取りは単純な文字数で、文や段落の区切りは見ません。そのため値はたいてい単語の途中で終わります — 上の例もそうです。本文が完全なものだとモデルに伝えるプロンプトは、2 画面分を超えるページでは必ず誤りになります。
{{webSummary}}
自分の LLM プロバイダーが書いたページの要約です。これは別のモデル呼び出しで、ページ単位でキャッシュされ、一度だけ作られてそのページのすべての段落で再利用されます。
A technical blog post arguing that timestamps should be stored in UTC and rendered in the reader's local zone. It identifies three failure points — form input, database column type, and output formatting — and recommends a single rule for all three. Written for backend developers; uses PostgreSQL column types as examples.これには AI スマートコンテキスト(設定 → 翻訳 → ページ翻訳)が必要です。オフのときは差し込む要約がないため、この変数は下に挙げる代替文字列になります。デフォルトのプロンプトは {{webSummary}} を使っているので、スマートコンテキストをオフのままにしていると、デフォルトのシステムプロンプトには常に Webpage summary: No summary available と書かれることになります。
{{videoSummary}}
字幕側の対応物です。動画の要約で、こちらも AI スマートコンテキストが前提、オフのときは同じく代替文字列になります。
A conference talk on time zone handling in web applications. The speaker walks through a production incident caused by naive timestamps, then demonstrates a UTC-in, local-out pattern. Names mentioned: PostgreSQL, Temporal, Luxon.値が取れないとき
変数が空のまま残ることも、消えることもありません。値がない、空、空白だけのいずれかの場合、Read Frog は決まった英文に置き換えます。
| 変数 | 代わりに入る内容 |
|---|---|
{{webTitle}} | No title available |
{{webDescription}} | No description available |
{{webContent}} | No content available |
{{webSummary}}、{{videoSummary}} | No summary available |
そのため、メタ情報が何もなく、スマートコンテキストもオフのページでは、デフォルトのシステムプロンプトはこう届きます。
## Document Metadata for Context Awareness
Webpage title: No title available
Webpage summary: No summary availableこれがいちばん影響するのは few-shot の例を書くときです。ページのタイトルから例を組み立てるプロンプトは、タイトルのないページでは「No title available」というページについての例をモデルに見せることになり、モデルはその一文を翻訳したり、それについて論評したりします。プロンプトがメタ情報の変数に頼っているなら、値が「No ... available」だったときにどうするかをプロンプト自身に書いてください。
{{input}} と {{targetLanguage}} には代替値がありません。{{targetLanguage}} には常に値があり、{{input}} はその段落そのものです — 空のテキストにリクエストが送られることはありません。
このあとに起きること
置換が済んだテキストはリクエストの全部ではありません。このあとルールブロックと自分の用語集の用語が追加され、出来上がった結果が翻訳キャッシュのキーになります。リクエストの組み立て方を参照してください。
