2015年10月19日
プラグインを活用してMTMLをシンプルで美しくする
PowerCMS をリリースして間もなく8年になります。お手伝いしたウェブサイトの数は 1000を超え、より大きなウェブサイト、より複雑な要件を実現したいという要望も増えてきています。
一方、MTML (Movable Type Markup Language) は柔軟であり、多機能であり、多くの要件がテンプレートだけで実現できます。ところが、MTMLが多機能であることを前提に複雑なテンプレート、特に条件分岐やループ等のロジックを駆使したテンプレートは「見通しが悪く」「修正に弱く」「他の人が理解しづらい」ものになる傾向があります。
現在の天気を表示するテンプレートを例にして
例として、OpenWeatherMap のAPIを利用して都道府県の現在の天気を表示するテンプレートを取り上げます。
取得するソースは下記です。
<img src="http://openweathermap.org/img/w/03n.png" alt="曇り">
※このサンプルを試すにあたっては OpenWeatherMap の API Key を取得しておいてください。
プラグインを活用しないケースと活用するケースを比較して紹介したいと思いますが、外部ファイルの取得とJSONデータをテンプレート変数にチェックする機能は標準のMTにはないので、下記の addons/plugins を利用する前提とします。ただし、プラグインを前提としないサンプルについてはプラグインが提供する機能、テンプレートタグは最低限の利用とします。
JSON データを取得して JSON データをテンプレート変数にセットする
<mt:FileGetContents url="http://api.openweathermap.org/data/2.5/weather?q=Tokyo,jp&APPID=[APIキー]" json2vars="weather">
「mt:FileGetContents」は DynamicMTML が提供するタグ、json2vars モディファイアは MTGetHashVar プラグインが提供するグローバルモディファイアです。
<mt:FileGetContents url="http://api.openweathermap.org/data/2.5/weather?q=Tokyo,jp&APPID=[APIキー]" json2vars="weather">
<mt:GetVarDump name="weather">
セットされたテンプレート変数は下記の通りです。
weather =>
array(12) {
["coord"]=>
array(2) {
["lon"]=>
float(139.69)
["lat"]=>
float(35.69)
}
["weather"]=>
array(1) {
[0]=>
array(4) {
["id"]=>
int(802)
["main"]=>
string(6) "Clouds"
["description"]=>
string(16) "scattered clouds"
["icon"]=>
string(3) "03n"
}
}
["base"]=>
string(8) "stations"
["main"]=>
array(5) {
["temp"]=>
float(292.04)
["pressure"]=>
int(1018)
["humidity"]=>
int(63)
["temp_min"]=>
float(291.15)
["temp_max"]=>
float(293.15)
}
["visibility"]=>
int(16093)
["wind"]=>
array(1) {
["speed"]=>
int(1)
}
["clouds"]=>
array(1) {
["all"]=>
int(40)
}
["dt"]=>
int(1445245080)
["sys"]=>
array(6) {
["type"]=>
int(1)
["id"]=>
int(7622)
["message"]=>
float(0.026)
["country"]=>
string(2) "JP"
["sunrise"]=>
int(1445201450)
["sunset"]=>
int(1445241669)
}
["id"]=>
int(1850147)
["name"]=>
string(5) "Tokyo"
["cod"]=>
int(200)
}
MT標準のテンプレートで IMGタグを組み立てる
さて、MT標準のテンプレートタグでこのデータから IMGタグを組み立てるテンプレートは以下のようになります。
<mt:FileGetContents url="http://api.openweathermap.org/data/2.5/weather?q=Tokyo,jp&APPID=[APIキー]" json2vars="weather">
<mt:Ignore>====キー「weather」を「_weather」にセット====</mt:Ignore>
<mt:Loop name="weather">
<mt:If name="__key__" eq="weather">
<mt:SetVar name="_weather" value="$__value__">
</mt:If>
</mt:Loop>
<mt:Ignore>====「_weather」が配列なので0番目の値を改めて変数「_weather」にセット====</mt:Ignore>
<mt:Loop name="_weather">
<mt:SetVar name="_weather" value="$__value__">
</mt:Loop>
<mt:Ignore>====ループを回して「main」「icon」「description」を変数にセット====</mt:Ignore>
<mt:Loop name="_weather">
<mt:If name="__key__" eq="main">
<mt:SetVar name="weather_main" value="$__value__">
</mt:If>
<mt:If name="__key__" eq="icon">
<mt:SetVar name="weather_icon" value="$__value__">
</mt:If>
<mt:If name="__key__" eq="description">
<mt:SetVar name="weather_description" value="$__value__">
</mt:If>
</mt:Loop>
<img src="http://openweathermap.org/img/w/<mt:Var name="weather_icon">.png" alt="<mt:Var name="weather_description">">
ループを何度か回すことで、MT標準のテンプレートタグで IMG要素がセットできることがわかるかと思います。但しこのコードでは、IMG要素の alt属性値は英語のままです(例:scattered clouds)。
これを日本語に翻訳するには後半を下記のように変更します。
<mt:Ignore>====「weather_description」を日本語に翻訳====</mt:Ignore>
<mt:If name="weather_description" eq="clear sky">
<mt:SetVar name="weather_description_ja" value="晴天">
<mt:ElseIf name="weather_description" eq="few clouds">
<mt:SetVar name="weather_description_ja" value="晴れ">
<mt:ElseIf name="weather_description" eq="scattered clouds">
<mt:SetVar name="weather_description_ja" value="曇り">
<mt:ElseIf name="weather_description" eq="broken clouds">
<mt:SetVar name="weather_description_ja" value="曇り">
<mt:ElseIf name="weather_description" eq="shower rain">
<mt:SetVar name="weather_description_ja" value="豪雨">
<mt:ElseIf name="weather_description" eq="rain">
<mt:SetVar name="weather_description_ja" value="雨">
<mt:ElseIf name="weather_description" eq="thunderstorm">
<mt:SetVar name="weather_description_ja" value="雷雨">
<mt:ElseIf name="weather_description" eq="snow">
<mt:SetVar name="weather_description_ja" value="雪">
<mt:ElseIf name="weather_description" eq="mist">
<mt:SetVar name="weather_description_ja" value="霧">
</mt:If>
<mt:Ignore>====アイコンを取得して、alt属性には翻訳した値をセット====</mt:Ignore>
<img src="http://openweathermap.org/img/w/<mt:Var name="weather_icon">.png" alt="<mt:Var name="weather_description_ja">">
追記 (If文で翻訳するよりも下記のように MTSetvars を使った方がスマートでしょう)
<mt:SetVars>
clear_sky=晴天
few_clouds=晴れ
scattered_clouds=曇り
broken_clouds=曇り
shower_rain=豪雨
rain=雨
thunderstorm=雷雨
snow=雪
mist=霧
</mt:SetVars>
<mt:var name="weather_description" replace=" ","_" setvar="translate_key">
<mt:var name="$translate_key">
プラグインが提供するタグ、機能を使ってテンプレートを書き直す
GetHashVarプラグインが提供する MTGetHashVar ファンクションタグを使えば、このテンプレートは(翻訳の部分を除けば) たったの2行で書けます。
<mt:FileGetContents url="http://api.openweathermap.org/data/2.5/weather?q=Tokyo,jp&APPID=[APIキー]" json2vars="weather">
<img src="http://openweathermap.org/img/w/<mt:GetHashVar name="weather" key="weather","0","icon">.png" alt="<mt:GetHashVar name="weather" key="weather","0","description">">
翻訳については Translate プラグインを使うことにします。ダイナミック専用ですが、ブラウザの言語を見て適切な言語に変換してくれる機能を提供するものです。
plugins/Translate/php/l10n/l10n_ja.phpを編集する
天気を表すテキストの翻訳をハッシュの形式で記載します。
<?php
$Lexicon = array(
'clear sky' => '晴天',
'few clouds' => '晴れ',
'scattered clouds' => '曇り',
'broken clouds' => '曇り',
'shower rain' => '豪雨',
'rain' => '雨',
'thunderstorm' => '雷雨',
'snow' => '雪',
'mist' => '霧',
);
?>
最終的なテンプレートは下記のようになります。コメントを除けば3行で完結します。
<mt:FileGetContents url="http://api.openweathermap.org/data/2.5/weather?q=Tokyo,jp&APPID=[APIキー]" json2vars="weather">
<mt:Ignore>==== 'weather' => '0' => 'description' を取得して日本語に翻訳====</mt:Ignore>
<mt:GetHashVar name="weather" key="weather","0","description" setvar="weather_description">
<mt:Ignore>====アイコンを取得して、alt属性には翻訳した値をセット====</mt:Ignore>
<img src="http://openweathermap.org/img/w/<mt:GetHashVar name="weather" key="weather","0","icon">.png" alt="<mt:Translate phrase="$weather_description">">
プラグインを嫌うのか、テンプレートの可読性・美しさを追求するのか
大規模なプロジェクトにおいては、「修正に強く、わかりやすい」ことを優先すべきです。コストを考えても、テンプレートの作成工数は大きく縮減できる筈です。 ちなみに、バージョンアップの際の互換性の問題が生じるのはほぼ Transformer プラグインと考えて良いです。テンプレート・タグがバージョンアップで互換性を失わせることはほぼありません。
プラグイン作成者とテンプレート作成者の分業こそが、MT、MTMLの本質なのです。
コメントを投稿する