変数とマルチサイト再利用
1つのテンプレートをネットワークに変えるのが変数です。変数の設計が正しければ、100サイトが1つのソースからレンダリングされます。間違っていれば、プリセットごとに手でテキストを貼り続けることになります。
3つの供給源、1つのスコープ
レンダリング時、ほとんどのエンジンは3か所からの変数を1つの参照テーブルに統合します。テンプレートが %SomeName% を読むと、リゾルバーがそのテーブルをたどって値を差し込みます。
- テンプレートローカルのヘルパー。テンプレート本文の中で
#setまたは#defで宣言します。 - サイト変数。テナントごとに定義され — 1サイト1レコードで、そのサイトのすべてのテンプレートが共有します。
- ランタイム変数。呼び出し時にリゾルバーへ渡されます(記事のコンテキスト、システム、ユーザー)。
執筆時の判断は、結局どの層がその事実を持つのか、に集約されます。
#set によるローカルヘルパー
1つのテンプレートの中だけで使う短命なヘルパーには #set を使います:
#set %Lead% = {Welcome|Greetings|Hello}
%Lead% to %brand_name%!
よい使い方:
- そのままだと本文が繰り返しで散らかる、1テンプレート限りのヘルパー;
- 同じテンプレート内で何度も出てくる長いフレーズ;
- 入れ子が深くなって目が疲れるときの、読みやすさのため。
悪い使い方:
- テナント固有の事実 — それはサイト変数のものです;
- ランタイムがすでに提供しているもの — ローカルの
#setは優先順位争いに負けます。
つまずきやすい構文ルール
- 変数名は大文字と小文字を区別しません。
- ASCIIのみ:英字、数字、アンダースコア。スペースもハイフンも不可。
#setは行頭にあるときだけ機能します。- コメントは
/# ... #/で書き、処理の前に取り除かれます。 - 未知の変数はそのまま残ります。
%MissingVar%は空文字列でもエラーでもなく%MissingVar%として出力されます。残骸はQAの不具合として扱ってください。
サイト変数 — マルチサイトの増幅装置
共有テンプレートが多数のサイトを、どのドメインでも同じ読み味にならずに支えられるのは、サイト変数のおかげです。
一般的なサイトプリセットはこうなります:
#set %BrandTone% = {practical|no-nonsense|straightforward}
#set %Industry% = SaaS analytics
#set %TopFeatures% = [<minsize=3;maxsize=4;sep=", ";lastsep=" and ">dashboards|alerting|audit logs|SSO|role-based access]
#set %Audience% = {teams|product leads|operations}
これで共有テンプレートは %BrandTone% や %TopFeatures% などを読めるようになり、誰もテンプレートに触れないままサイトごとに出力が変わります。
サイト変数を作るタイミング
| サイン | 対応 |
|---|---|
| そのフレーズが2つ以上のテンプレートに出てくる | サイト変数へ抜き出す。 |
| その事実がサイトごとに変わる | サイト変数でなければならない。 |
| リストをシャッフルしたい、あるいはサイトごとに変えたい | 順列を中に入れたサイト変数。 |
| 1つのテンプレートで1回しか使わない | たいていはそのまま埋め込む。 |
ランタイム変数
ランタイム変数は呼び出し側のコンテキストから来ます:レンダリング中の記事、現在のユーザー、システム時計。同名のサイト変数やローカルヘルパーより優先されます。
エンジンをまたいでよくあるランタイム変数(名前は実装によります):
%year%— 現在の年%lang%— 現在の言語コード%site_domain%— 現在のサイトのホスト%brand_name%、%product_name%— 記事が扱うブランド/製品%article_topic%、%category%— 記事レベルのメタデータ
書き手がテンプレートからこれらに代入することはありません。読むだけで十分です。
変数の優先順位
同じ名前が複数の層に存在する場合、優先度の高い方が勝ちます。標準的な順序は、強い方から:
- ランタイム変数
- サイト変数
- システム変数
- テンプレートローカルの
#set
実務上の帰結:ランタイムが %brand_name% を渡しているなら、テンプレート内の #set %brand_name% = Demo は何もしません。ランタイムが勝ちます。ランタイムを覆い隠さないヘルパー名を選んでください。
命名規約
特定のスタイルより、1つのプリセット内での一貫性が大事です。とはいえ妥当な既定はあります:
- ランタイム変数:たいてい
lowercase_snake_case。あなたの管理外に存在します。 - サイト変数:通常の文字列は
PascalCase、文法的な変形にはPascalCaseWithSuffix。 - リスト変数:複数形にします(
%TopFeatures%、%SupportedLanguages%)。 - ローカルヘルパー:短く分かりやすく —
%Lead%、%Closing%。
複合変数
サイト変数はお互いを参照できます。プリセットのリゾルバーは変数間の参照を先に差し込み、入れ子のspintaxは生のまま残すので、後の再抽選もそのまま働きます:
#set %FoundedLine% = launched in %FoundedYear%, based in %HQ%
#set %Pitch% = {fast|lightweight|self-hosted} %ProductCategory%
繰り返す事実は複合変数で一度だけ組み立て、テンプレートをまたいで使い回してください。
再抽選の落とし穴
初めての人がいちばん混乱するのがここです。変数が生のspintaxを含んでいると、出現するたびに独立して抽選し直されます。
#set %Tone% = {safe|trusted}
%Tone% and %Tone%
あり得る出力:
Safe and trusted
#set の変数が一度解決されてあとは同じ値を返す、とは考えないでください。異なる2つの形容詞が必要なら、変数を2つ使います。
厳密な繰り返しが必要なとき:#def
上のルールはマクロである #set の話です。姉妹ディレクティブの #def は同じ形をしていて、逆のことをします:値をレンダリングごとに一度解決し、同じ結果をすべての参照に渡します。
#def %Tone% = {safe|trusted|secure}
%Tone% and %Tone%
これで2か所は常に一致します —「safe and safe」「trusted and trusted」— どちらの参照が埋まるより前に、抽選が一度だけ起きたからです。2つのディレクティブの違いはそれだけで、他(行に紐づく、1行に1つ、出力からは消える、名前のルールも同じ)はすべて同一です。
テンプレート全体で値が安定していなければならないときは #def を選びます:{plural} ブロックに渡す数、複数形のスロットから引き上げた名詞、意図して繰り返すフレーズなど。変化を望むときは #set です — 本文ではそちらが普通です。
はっきり言っておくべき注意が1つ。#def が保証するのは、1つの変数がそれ自身と一致することです。異なる2つの変数を連動させはしません — #def はそれぞれ独立に抽選するので、%Noun% と %NounGenitive% が別々の語に落ちることはあり得ます。2つの値が互いに一致しなければならないときは、2つの変数ではなく1つの列挙の中で束ねてください。
省略可能な断片
列挙の中の空の分岐は、省略可能な断片になります:
{|official }website
{fast|secure|} withdrawals
断片が消える可能性があるなら、スペースは分岐の内側に置きます。そうしないと二重スペースや単語の癒着が起きます。省略可能なリスト(空になり得る順列)は、順列全体を包みます:
{|[<minsize=2;maxsize=3;sep=", ";lastsep=" and ">Slack|Jira|Linear]}
エンジンは順列から0個を選べません。「リストがまったく出ない」を可能にする唯一の方法が、この包み方です。
区切り文字の衝突
よくあるレンダリングのバグ:リスト変数の中にすでに and があるのに、周りの本文がもう1つ and を足してしまう。
%Integrations% and other tools
%Integrations% が Slack, Jira, and Linear に解決されると、最終的な本文はこうなります:
Slack, Jira, and Linear and other tools
直し方:
- カンマを入れる:
%Integrations%, and other tools; - 組み替える:
{Besides|Along with} %Integrations%, other tools...; - 末尾の接続詞をやめて、コロンやダッシュにする。
lastsep=" and " の順列の後ろに and で始まる固定文が続く場合も同じです。出す前にいくつかバリエーションをプレビューしてください。
変数かインラインのspintaxか
| 変数を使う | インラインのspintaxを使う |
|---|---|
| フレーズがテンプレートをまたいで繰り返す | 1つの文の中の使い捨ての類語 |
| 事実がサイトごとに変わる | 一般的な動詞・名詞の類語 |
| リストをテナントごとに変えたい | 小さくて固定の使い捨てリスト |
| 文法上の形が複数の綴りを必要とする(文法ガイドのロシア語の格ENを参照) | 1つの文法的位置でしか使わない語 |
目安:小さなインラインの類語枠を足す前に、繰り返す・文法に敏感なフレーズを変数へ抜き出す。変数なら間違いを直す場所が1か所で済みます。インラインは、それを散らかします。
変数でよくある間違い
| やらないこと | 理由 | 代わりにすること |
|---|---|---|
| テナント固有の事実を共有テンプレートに直接書く | すべてのサイトが同じ本文を出し、マルチサイト再利用の意味がなくなります。 | その事実をサイト変数へ移す。 |
#set でランタイム変数を上書きしようとする | ランタイムが常に勝つので、上書きは静かに無効になります。 | ランタイム名を覆い隠さないようヘルパーを改名する。 |
%X% ... %X% が同じ語を繰り返すと思い込む | 出現ごとに抽選し直されます。別々の語になり得ます。 | 文を書き直すか、別々の変数を2つ使う。 |
| 変数が無いとエラーになると思い込む | そのまま %MissingVar% として出力されます。 | 残った %...% を検出するプレビュー工程を入れる。 |
| リスト変数にもう1つ「and」を連結する | 「A, B, and C and other things」になります。 | カンマにするか、組み替える。 |
| 省略可能な断片のスペースを忘れる | 二重スペースや単語の癒着になります。 | スペースは省略可能な分岐の内側に置く。 |
変数設計のチェックリスト
- テナント固有の事実は、共有テンプレートではなくサイト変数にある。
- 記事固有の事実は、
#setではなくランタイム変数にある。 #setのヘルパー名がランタイム変数を覆い隠していない。- 変数名はASCIIで、スペースもハイフンもない。
- 繰り返し使う変数はすべて、再抽選の影響を確認済み。
- 省略可能な断片は、分岐の内側で空白を処理している。
- 接続詞が続くリスト変数は、区切り文字の衝突を確認済み。
- 解決済みのサンプル5本に
%...%の残骸がない。
構造に進む準備はできましたか。次のガイドは実践・順列です — 多様性が実際に生まれる場所です。