変数とマルチサイト再利用

1つのテンプレートをネットワークに変えるのが変数です。変数の設計が正しければ、100サイトが1つのソースからレンダリングされます。間違っていれば、プリセットごとに手でテキストを貼り続けることになります。

3つの供給源、1つのスコープ

レンダリング時、ほとんどのエンジンは3か所からの変数を1つの参照テーブルに統合します。テンプレートが %SomeName% を読むと、リゾルバーがそのテーブルをたどって値を差し込みます。

  1. テンプレートローカルのヘルパー。テンプレート本文の中で #set または #def で宣言します。
  2. サイト変数。テナントごとに定義され — 1サイト1レコードで、そのサイトのすべてのテンプレートが共有します。
  3. ランタイム変数。呼び出し時にリゾルバーへ渡されます(記事のコンテキスト、システム、ユーザー)。

執筆時の判断は、結局どの層がその事実を持つのか、に集約されます。

#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% — 記事レベルのメタデータ

書き手がテンプレートからこれらに代入することはありません。読むだけで十分です。

変数の優先順位

同じ名前が複数の層に存在する場合、優先度の高い方が勝ちます。標準的な順序は、強い方から:

  1. ランタイム変数
  2. サイト変数
  3. システム変数
  4. テンプレートローカルの #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本に %...% の残骸がない。

構造に進む準備はできましたか。次のガイドは実践・順列です — 多様性が実際に生まれる場所です。


シリーズを続ける