font-family 指定を見る側が選べるようにしてみる

ある料理店があった。料理は「コックおすすめのワイン」とセットだった。

ある日コックは考えた。「人はみな自分好みのワインがあるに違いない。俺の好みを押し付けるのはやめてみるか」。それ以降、この料理店は「ワイン持ち込み自由」になった。「これでお客さんはもっと料理を楽しんでくれるだろう」。

ところが大半の客は持ち込みなどしない。料理の前に出される水と一緒に食べるだけなのだ。コックは愕然とした。「俺の料理を、まるで流し込むように水で食べるなんて」。

また以前のやり方に戻すことにした。必ず「おすすめワイン」で食べてもらう。多くの客は喜んだ……かどうかわからない。どうでもよかったのだ。もし聞かれれば「そう言えば水よりはこのワインのほうが、料理がおいしく感じられるね」と答える。だが、あっちの店に行ったときに茶が出されるのなら茶、ビールならビールにするだけだ。自分で選べるなどと考えたこともなかった。だからどこでどう手に入れるかどころか、ワインの自分の好みすら知らなかったのだ。

コックは悩んだ。多くの客が水で食べるよりましな状態にはなった。しかしごく少数とは言え、各々こだわりのワインを持ち込んで料理を楽しんでくれていた客はどうなるのか。いちばんよくわかってくれている彼らの思いを踏みにじるのか……。

フォントを指定しないこと

以前、「フォントの指定をやめる」と題して記事を書きました。そのときには

「本文は明朝系」という信念の人(私だ)はブラウザのデフォルトを serif に設定しているだろうし、Windows でも自分の好みの表示になるようにがっちり設定している人には、そのフォントで読めるようにしてあげればいいではないか。

という訳で、このページの本文の font-family の指定はやめることにした。

と考えていたのです。

数年ぶりに WordPress のテーマを変えてみて、それが元々は欧文向きとは言え、文章を読ませるのに適したデザインでセリフ系のフォントを指定してあったこと、そのフォントを入れ替えてみようとしたことから、いろいろと考えながら調べているうちに、「Windows でも自分の好みの表示になるようにがっちり設定」することがほとんど不可能らしいことに気がつきました。

私は長いこと、デスクトップに Debian を使っています(Windows はどうしてもそれでしか動かないソフトを使う必要があるときだけなので、その際の見かけなど細かいことはまったく気にしないことにしています)。現在の Debian なら fontconfig で、たとえば

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
    <match target="pattern">
        <test qual="any" name="family">
            <string>serif</string>
        </test>
        <edit name="family" mode="prepend" binding="strong">
            <string>IPAexMincho</string>
            <string>DejaVu Serif</string>
        </edit>
    </match>
</fontconfig>

のように設定することで、総称名 serif だけが指定されたときに使われるフォントを設定できます(もっと正しい書き方があるかもしれませんが)。

これでも随分と簡単になったものです。以前は defoma とかいうのがあって、その hints という設定ファイルを書くのがものすごく面倒でした。TrueType のフォントファイルを所定のフォルダに置くだけですぐに使える Windows などがとても羨ましく思えたものでした(Mac はよく知らない)。

それが周回遅れでトップに立ってしまったようなものです。Windows では「serif という総称名で表示される実際のフォントを設定する方法」が(少なくとも簡単には)ないのです(Mac はよく知らない)。web ブラウザーで設定できるかと思ったら Windows10 標準の Edge では、それすらもできないようです。

それでも Firefox では about:preferences#content の「フォントと配色」の詳細設定で、また Chrome では chrome://settings/fonts の詳細設定で、だいぶ設定できそうです。Safari はよくわかりませんが、ユーザー定義のスタイルシートを書けばできるらしいです。そういえば Firefox でも、userContent.css というユーザー定義のスタイルシートでもできそうですし、Chrome でも拡張機能でユーザー定義スタイルシートを使えそうです。

しかし、そこまでしてデフォルトのフォント設定をしている閲覧者はどれほどいるのでしょう。結局、「フォントの指定をやめる」というのは、そのようにデフォルトの設定も行っていない“意識の低い”閲覧者に対して何も与えないものでした。

フォントを指定すること

では、サイト制作者側できっちりフォントを指定してやればいいのでしょうか? ちょっと検索すれば「font-family 指定のおすすめ」のような記事がたくさん見つかります。たとえば

body {
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Yu Gothic", YuGothic, "ヒラギノ角ゴ ProN W3", Hiragino Kaku Gothic ProN, Arial, "メイリオ", Meiryo, sans-serif;
}

みたいにするのがいいのでしょうか?

今度は“意識の高い”閲覧者を切り捨てていることになってしまいます。「sans-serif ゴシック系より serif 明朝系」とか、ヒラギノと游のどちらがいいかはほんとうに好みによりそうだし、さらにはもっといい(自分好みの)フォントを自分でインストールしてそれをデフォルトに設定している閲覧者に対して、その意図を無にしてしまうことになると思うのです。

閲覧者が選べるスイッチ

ブラウザーでもっと手軽にフォントを切り替えるボタンがついていればいいのでしょうが、現実にそういうものはありません。ズームは割と簡単にアクセスできるメニューやキーボードショートカットが用意されているのに。そういえば、そういうものがあるのにコンテンツの側で「文字の拡大・縮小」を用意しているサイトもときどき見かけますね。……というところで、そうかフォント切替スイッチをコンテンツ側で用意するという方法もあるのか、と思いつきました。

まずは「明朝体/ゴシック体の切替」の二択のボタンです。Javascript の element.classList.toggle を使えば簡単です。

CSS のほうで

body {
        font-family: Georgia,Times,"Times New Roman","YuMincho","Yu Mincho","Hiragino Mincho ProN",serif;
}
.sans {
        font-family: -apple-system,BlinkMacSystemFont,sans-serif;
}

のように、<body> に class=”sans” のない場合とある場合の font-family 指定を書いておき、HTML のほうには

<button id='toggle-font-button' title='明朝体/ゴシック体の切替' onclick='(function(){document.getElementsByTagName("body")[0].classList.toggle("sans");})()'>フォント切替</button>

をどこかに追加すれば済みます。

WordPress での実践

「ヒラギノ明朝優先」「游明朝優先」……と選択肢を増やすときは、CSS で用意する class を増やして、HTMLでは element.classList.toggle の代わりに element.classList.removeelement.classList.add を使います。

style.css で

body {
        font-family: Georgia,Times,"Times New Roman","YuMincho","Yu Mincho","Hiragino Mincho ProN",serif;
}
.serif {
        font-family: Georgia,Times,"Times New Roman",serif;
}
.hiramin {
        font-family: Georgia,Times,"Times New Roman","Hiragino Mincho ProN","YuMincho","Yu Mincho",serif;
}
.yumin {
        font-family: Georgia,Times,"Times New Roman","YuMincho","Yu Mincho","Hiragino Mincho ProN",serif;
}
.sans, .sans-serif {
        font-family: -apple-system,BlinkMacSystemFont,sans-serif;
}
.hirago {
        font-family: -apple-system,BlinkMacSystemFont,"Hiragino Kaku Gothic ProN",Meiryo,sans-serif;
}

のように用意しておき、functions.php で

add_action( 'get_footer', 'fontSwitcher' );
function fontSwitcher () {
?>
<script type="text/javascript">
  var body = document.getElementsByTagName("body");
  function resetFontClass () {
        body[0].classList.remove("serif", "hiramin", "yumin", "sans", "hirago");
  }
  function addFontClass ($class) {
        resetFontClass();
        body[0].classList.add($class);
  }
</script>
<div id="fontswitcher">
  «
  <form id="fontswitcherform">
        <input type="radio" name="fontswitcher" onClick="addFontClass('serif')"><span class="serif">serif</span><br/>
        <input type="radio" name="fontswitcher" onClick="addFontClass('hiramin')"><span class="hiramin"> ヒラギノ明朝</span><br/>
        <input type="radio" name="fontswitcher" onClick="addFontClass('yumin')"><span class="yumin"> 游明朝</span><br/>
        <input type="radio" name="fontswitcher" onClick="addFontClass('sans')"><span class="sans"> sans-serif</span><br/>
        <input type="radio" name="fontswitcher" onClick="addFontClass('hirago')"><span class="hirago"> ヒラギノ角ゴ</span><br/>
  </form>
</div>
<?php
}

としました。add_action( 'get_footer' )で最後のほうに付け加えました。スイッチのデザインは style.css で行います。

こういうものを作ってここに付けてみましたが、他で似たようなものを見かけたことはまったくありません。必要ないか流行らないか、はたまた弊害があるのかもしれません。

***

コックが考え出した新しいやり方はこうだ。

何も言わない客には「おすすめワイン」をセット。だがちょっとだけ好みがある客にはテイストの違ういくつかの中から選んでもらおう。そして知識もあり手間も厭わぬこだわりの客には自分のワインで楽しんでもらおう。

さあ、この料理店は繁盛するだろうか……。

特定の文字だけ別のフォントを使う

まとめ

まとめを先に書いておきます。

特定の文字コードのみ(ここでは「除算記号」(U+F7))別のフォントを使いたい場合、まずそれについて定義します。

  @font-face {
    font-family: 'division sign';
    src: local('Georgia'),local('Times'),local('Times New Roman'),local('Serif');
    unicode-range: U+F7;
  }

その後に全体で使うフォントを定義します。ここでは Google Fonts から読み込む CSS で

...
/* latin */
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400;
  src: local('Lora Regular'), local('Lora-Regular'), url(https://fonts.gstatic.com/s/lora/v10/4vqKRIwnQQGUQQh-PnvdMA.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
...

などです。それらの後で、実際に使用するフォントを指定します。

body {
	font-family: "division sign",Lora,Georgia,Times, ... ;
}

この定義と指定の順番を入れ替えてはなりません。

web フォント Lora のうち「除算記号」だけ使わない

結論を先に書いた後でゆっくり経緯を書きます。

このブログでの欧文フォントに Google の web フォント Lora を使うことにしました。デザインがとても気に入っています。

ところでこの Lora で「除算記号」は、真ん中の水平線がなく、コロン「:」にそっくりのデザインになっています。除算記号としてこの形のものを使う地域がある、ということを聞いたことがあります。

Lora の除算記号÷
Georgia の除算記号÷

その違いがうまく表示されているでしょうか。

通常の文章なら除算記号などめったに出てくるものでもなく、たいした問題ではないでしょう。ところが、このブログ「半月記」での一番人気の記事は

なのです。ここで除算記号が、日本でおなじみの形ではなく、すべて「:」そっくりになっていたら、読者は訳がわからなくなってしまいかねません。これらの記事の中の主張のひとつが「除算記号などごく限られた領域でしか使われないのだ」なのですが、その内容を書くためには除算記号を使わなければならず、そのデザインにまでこだわらなければならないとは、なんと皮肉なことでしょう。

@font-faceunicode-range

全体的には Lora をたいへん気に入っているので使い続け、「除算記号」のみ別のフォントで表示するようにしてみます。

CSS の @font-face には unicode-range という記述子がありますので、これを使います。このリンク先の例にあるのとほぼ同じように

  @font-face {
    font-family: 'division sign';
    src: local('Georgia'),local('Times'),local('Times New Roman'),local('Serif');
    unicode-range: U+F7;
  }

のように書きます。文字コードU+F7(つまり「除算記号 division sign」)の場合のみ、Lora ではなく、Georgia, Times, “Times New Roman”, Serif のどれかを使うようになります。

定義の順序

さて、そもそも web フォント Lora を使うためには、CSS に定義 @font-face があるはずです。ここでは外部 CSS として Google Fonts より読み込んでいます。

これらの定義があれば

body {
	font-family: "division sign",Lora,Georgia,Times, ... ;
}

のように使用フォントを指定して、意図通りになるはずでした。しかし実は、それらの記述の順序が大事でした。まず局所的なフォント定義(‘division sign’)が最初、それから全体のフォント定義(Lora)、最後にフォント指定、の順番でなければなりません。

WordPress での実践

ここでは WordPress の子テーマを使っています。子テーマの style.css のはじめのほうに局所的なフォント定義(‘division sign’)を書いても、それより前に外部 CSS の読み込めば、正しい順番になりません。もし 子テーマの style.css より後に外部 CSS 読み込みをもってきても、やはり正しい順番にはなりません。

そこで局所的なフォント定義を分離して先に読み込むようにします。この部分はたいした量でもなく、あとで書き換えることもまずないので別ファイルにせず、functions.php に直接書いて読み込ませることにしました。そして優先度を上げ(10より小さく)ます。

add_action( 'wp_head', 'division_sign_font', 7 ); /* 8 だと遅すぎる */
function division_sign_font() {
?>
<style type='text/css'>
  @font-face {
    font-family: 'division sign';
    src: local('Georgia'),local('Times'),local('Times New Roman'),local('Serif');
    unicode-range: U+F7;
  }
</style>

あとは、前の記事に書いたように、外部 CSS の読み込みと子テーマの style.css の読み込みの順番が正しくなるように優先度を付けます。

親テーマ指定の web フォントを子テーマで変更する

まとめ

まとめを先に書いておきます。

<head> 内で

<link rel='stylesheet' id='libre-lora-css' href='https://fonts.googleapis.com/css...' ... />
...
(親テーマ指定のwebフォント用CSSの削除)
...
<link rel='stylesheet' id='libre-2-style-css' href='...' ... />

の順になってほしいため、子テーマの functions.php では

add_action( 'wp_enqueue_scripts', 'libre_kid_fonts', 9 ); /* style.css より先に読み込む必要がある */
function libre_kid_fonts() {
        wp_enqueue_style( 'libre-lora', libre_lora_url(), array(), null );
}
add_action( 'wp_enqueue_scripts', 'libre_dequeue_google_fonts', 11 ); /* 優先度を落とす */
function libre_dequeue_google_fonts() {
        wp_dequeue_style( 'libre-2-fonts' );    
}

のように、add_action('wp_enqueue_scripts') に優先度を付ける必要があります。

WordPress のテーマ Libre 2 と Google web フォント Lora

では、結論を先に書いた後でゆっくり経緯を書いてみます。

ふと WordPress のテーマを変えてみました。もう自分で作る気力もないので、公式ディレクトリで人気順に見ていって、シンプルな Libre が気に入りました。すぐ後に WordPress.com のほうで後継 Libre 2 を見つけ、「ダウンロードしてインストール型 WordPress で使用できます」とあったので早速そうすることにしました。

いくつか直したいところがあったので、子テーマで手を入れることにしました。変更点を備忘録的にここに書いておくと、

  • フォント関連の変更。欧文フォントを Libre Baskerville からLora に変更した。
  • 装飾に Dashicons を使うことにした。
  • 記事の最初のメタ情報にカテゴリー・タグを表示することにした。記事の最後には表示しない。
  • 本文の段落は1字下げ。段落間は小さくする。箇条書きの上下のマージンも小さく。
  • 本文内の見出し(<h3>など)は上下にマージン。ただしその見出しが本文先頭なら上マージンなし。

このテーマは、やや長めの文章を見せるのに適するようにセリフ(serif)の書体 Libre Baskerville が指定してありました。そこで日本語で書かれるこのブログでも、セリフ(明朝体)にすることを考えます。ただ、よくあるヒラギノ明朝体や游明朝体の中に混ぜてみると Libre Baskerville は落ち着かない感じがして、同じく Google web フォント の Lora に変更することにしました。

wp_dequeue_style() の実行順序

親テーマの Libre 2 は、その functions.php で

function libre_2_scripts() {
        ...
        wp_enqueue_style( 'libre-2-fonts', libre_2_fonts_url(), array(), null );
}
add_action( 'wp_enqueue_scripts', 'libre_2_scripts' );

と、webフォント Libre Baskerville 用の CSS を google から読み込むようになっています。子テーマでは、ここで enqueue しているものを dequeue すればいいのです。

が、子テーマの場合、そもそも functions.php の実行順は (1)子テーマの functions.php (2)親テーマの functions.php です。したがって、子テーマの functions.php に普通に dequeue を書いてもこれが先に実行され(つまりまだ enqueue されていないものを dequeue しようとする)、その後に親テーマで euqueue されることになります。

そこで、子テーマでは dequeue の実行の優先度を下げて(10より大きな数字にして)書いておかなければなりません。

wp_enqueue_style() の実行順序

子テーマでは、親テーマの libre_2_fonts_url() を真似して、別のwebフォントである Lora 用の CSS を指定する libre_lora_url() を書きます。

この CSS は Google Fonts から読み込まれますが、内容は

...
/* latin */
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400;
  src: local('Lora Regular'), local('Lora-Regular'), url(https://fonts.gstatic.com/s/lora/v10/4vqKRIwnQQGUQQh-PnvdMA.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
...

のような @font-face がいくつも並んでいるものです。子テーマの style.css では

body {
	font-family: Lora,Georgia,Times, ... ;
}

のように、この定義を利用して使用フォントを指定します。

ところでこの 定義 @font-face と指定 font-family の順序ですが、ブラウザー Chromium の場合 (Debian の Chromium で確認しました。おそらくどの OS でもブラウザー Chrome でも同じだろうと思います)、前もって @font-face がないと font-family での指定時にそれが存在しないものと扱われるようです。Firefox ではその順番は関係ないようでしたが。

そこで、子テーマの style.css より前にこの CSS が読み込まれるように、wp_enqueue_style() を呼ぶ add_action('wp_enqueue_scripts') の優先度を 9 にします。

WordPress 10周年 (自分の中で)

しばらく何も書かずに間が空いてしまいました。

ふと気がついたらこのブログの最初の記事「WordPressの導入」を書いたのがちょうど10年前でした。それまでの手書き(というのも変ですが、テキストエディタで HTML タグを陽に書きながら、という意味)でWebサイトを作るというのがだんだん億劫になり、何かいいソフトはないものかと探してみてたまたま見つけたのが WordPress でした。その WordPress が現在、ここまで広まっていようとは夢にも思いませんでした。

WordPress の最大の強みのひとつは、このソフトウェアを取り巻くコミュニティの存在です。「ソフトウェアはコピーされても、コミュニティはコピーできない」という言葉を何度も思い出します。この10年のうちの長い時間を日本語版作成チームの一員として過ごせたことをとても光栄に思います。そういう関わりをしなければきっと私は WordCamp にも参加しなかっただろうし、いろいろな人たちに出会うこともなかったでしょう。

WordPress のもうひとつの強みは、これは私の思いですが、GPL を採用していることです。WordPress は、GPL の元で公開されているソフトウェアの中で最も成功しているもののひとつでしょう。GPL であることが今日の WordPress の隆盛の大きな要因だろうと思います。また逆に、WordPress は GPL の理念を広めるのにとてつもなく貢献している存在です。WordPress に接して初めて GPL を知った人は大勢いるのではないでしょうか(もしこれを読んでいるあなたが WordPress を利用しているなら自分のサイトの管理画面の左上の W マークをクリックして「自由について」というページを見てみてください。ここからリンクを張れないのが残念ですが、つまり URL は (自分のサイト)/wp-admin/freedoms.php です。WordPress をインストールして利用していてもこのページはあまり読まれていないでしょう。翻訳に関わった者としてちょっと残念に思っています)。

10年。けっこう長い時間です。たとえば WordPress や GPL をまったく知らない子どもだった人がそれらをよく知って利用するまでになるくらい。さてもう10年経ったら、WordPress や GPL はどう発展しているでしょうね。

Hubot ping の日本語化 — 「いるのか?」の正規表現

Hubot の ping コマンド

hubot_wapuuSlack というコミュニケーションツールを利用することになって、そこでこれは便利かもということで Hubot をいじってみています。

現時点での安定版 Debian Wheezy に Hubot をインストールするにはどうすればいいんだとか、Slack に連携させるときに Heroku を使う方法ならすぐに見つかるが、自前ホストのHubotとSlackを連携させるにはどうするんだとか、いくつか引っかかりながらも、ここにリンクした情報が既にあったのでうまくいきました。

この bot がちゃんと作動しているかどうか反応を見るのに、ping というコマンドがはじめからサンプルとして付属しています。bot の名前に ping と付けて問いかけると、PONG と答えるというものです。

user> hubot ping
hubot> PONG

さて、「HubotのScriptを翻訳するとかわいい」にありますように、日本語化すると愛着がわきます。ping の Script はとても簡単で、肝は

  robot.respond /PING$/i, (msg) ->
    msg.send "PONG"

です。使用目的はとにかく存在確認ですから、日本語にすると

  robot.respond /いるのか\?$/i, (msg) ->
    msg.send "はい、ここにいます!"

です。

また、Hubot を起動するときに bot 自身の名前と別名を付けることができます。そこでこれを日本語で

bin/hubot --name wapuu --alias わぷー

と付けてやると、ますます親しみがわきます。これで応答は

user> わぷー いるのか?
wapuu> はい、ここにいます!

となりました。

「いるのか?」のバリエーションの正規表現

このままですと、script の質問文のところは正規表現で書けるのに、ただ「いるのか?」に正確にマッチしないと返答しないということになっています。

「いるのか?」の分解存在確認の日本文「いるのか?」を考察してみます。これを4つ(疑問符を入れると5つ)に分けて、それぞれのバリエーションとその組み合わせを思いつくまま挙げてみました(図)。ありえない組み合わせ—たとえば、2段目が「ります」のとき、その前に「い」はありえない—の制限を付け加えながら、正規表現にして書いてみると、次のようになりました。

/(((い|ゐ|居)(て?))(?!り)|(お|を|居)|((い|居)(て?)は)(?!ま))((る|ん(?=の))|((り?)ます)(?!ん))((の?ん?)(です)?|(んだ)(?!か))?(か(い?な?|よ|ね)?|(よ?)(ね|な))?\s?(\?|?)/

これで、質問文は「いる?」から「いてはりますのんかいな?」(いや、これが現実にありうる表現かどうか確証は持てないのですが)まで対応できます。

ping の目的は存在確認なので、日本語では「生きてる?」とも言いそうです。1段目の前に「生きて」を付けて、元の1段目を必須から任意に変更すればよさそうです。さらに、「調子どう?」「元気?」というフレーズもよく使いそうですね。これはもうそのままということにします。だんだん手抜きになってきました。

結局、日本語版 ping はこうなりました。

  robot.respond /(((い|ゐ|居)(て?))(?!り)|(お|を|居)|((い|居)(て?)は)(?!ま))((る|ん(?=の))|((り?)ます)(?!ん))((の?ん?)(です)?|(んだ)(?!か))?(か(い?な?|よ|ね)?|(よ?)(ね|な))?\s?(\?|?)/i, (msg) ->
    msg.send "はい、ここにいます!"

  robot.respond /(い|生|活)きて(((い|ゐ|居)(て?))(?!り)|(お|を|居)|)?((る|ん(?=の))|((り?)ます)(?!ん))((の?ん?)(です)?|(んだ)(?!か))?(か(い?な?|よ|ね)?|(よ?)(ね|な))?/i, (msg) ->
    msg.send "はい、ここにいます。"

  robot.respond /(調子どう|元気)/i, (msg) ->
    msg.send "はい、元気です。"

wapuu_pingちゃんと数えていませんが、これで「いるのか?」を意味する数十種類の表現に答えることができるようになりました。

このWapuu bot は、WordPress の日本語コミュニティがこれから活用していこうとしている Slack にいます。WordPress 本体の開発元でこの Slack を使っていくことになったことに触発され、そこに収まりきれない話題—日本語圏特有の話題、日本語で話したほうが楽な話題など—を扱っていこうという場所です(たぶん)。単に「WordPressの使い方」を尋ねるような場所ではありませんが、何かちょっとでも手助けしたい(日本語圏で最も求められているのはたぶん翻訳です。本体のみならず多くのドキュメントやニュースなどが翻訳されるのを待っています。もちろんほかにも何かがあります。たとえばこの記事のように、どうでもいいような冗談を仕込むとかもきっと)と思っている方があればぜひ参加してみてください。参加資格などなく、参加方法の手続きを踏めさえすれば誰でも参加できます。Wapuu bot はそこで待っています。

『サイトの拡張性を飛躍的に高める WordPressプラグイン開発のバイブル』

事前にレビューする機会を与えられた書籍『サイトの拡張性を飛躍的に高める WordPressプラグイン開発のバイブル』が発売されました。

タイトルのとおり「プラグイン開発」に焦点を当てたもので、これまでの WordPress 関連書籍と一線を画しています。

まえがきに「開発者をターゲットとした WordPress の専門書」とあり、WordPress 固有のプラグインの仕組みの解説はもちろん、WordPress プラグイン開発に適した環境の構築から、コーディング規約、テスト方法まで、懇切丁寧に書かれています。これらをまとめて一瞥できるのは大変ありがたいことです。

WordPress の特徴としての GPL についてもひとつの章を充ててじっくりと説明されています。その上でのビジネスモデルにも言及されており、一読の価値があります。

そして開発したプラグインを公式ディレクトリで公開する方法も紹介されています。評者はこの本の出る少し前に初めて公開を前提としてプラグインを書き、公式ディレクトリに登録してみました。まったく大したものではありませんが、「公開」を念頭に置くと適当なことはできないので、ウェブであちこち検索して回ってできるだけきれいに、間違いのないようにとあらためて勉強することになりました。そのときにこの本があればかなり近道ができたはずです。

さて発売前のレビューの際に、細かな用字の指摘のほかにもやや大きな修正や加筆を必要とするようなコメントを著者に返しました。前者はともかく後者については、たぶん時間的にも分量的にも制約が大きかったのでしょう、残念ながら反映してもらうことができなかったものがありました。

そのひとつが、第8章「管理画面」の特に8-3節「管理画面を使って独自の設定を保存する」についてです。著者たちがあまりにプラグイン開発の経験に富んでいて、ずっと以前から WordPress に精通しているためか、旧来の手法による記述になっています。古いプラグインを読んで理解するにはいいかもしれませんが、これから新たに開発する場合にはこの箇所の記述のようにする必要はありません。WordPress の現在のバージョンには、より簡便で安全な手法 (Setteings API) が用意されています。せっかくこの年になって出版される日本語で初めて(たぶん)のプラグイン開発の解説書ですから、ぜひ Settings API に触れてほしかった—というか現状の8-3節と差し替えてもいいくらいでは—と思います。

そういった点はあるにしても、全体にこの本から受けることのできる恩恵は大きなものがあります。

評者は WordPress の単なるユーザーとなってから数年の時間が経過していますが、実際にプラグインを作ってみること、それも公開しても恥ずかしくないように書いてみることをやってみてはじめて、それまで適当にしか理解していなかったことについてもきちんと知る必要が出てきて、学ぶことが非常に多くありました。その経験をとおして WordPress そのものについての理解、ほかの人たちが作った便利なプラグインについての理解がかなり深まりました。

そういった意味で、この本が「ターゲットはプラグイン開発者」と謳っていても、一般のユーザーも手にとって読んでみるといいと思います。そして簡単なものでもいいので(最終的には公式ディレクトリに登録はしないにしても)「正しい」作法でプラグインを書いてみると、 WordPress をより理解し活用することにつながるでしょう。

WordPress プラグインやテーマの翻訳でうまく手を抜く(いい意味で)

WordCamp Kansai 2014 に行ってきました。2日め“コントリビューターデイ”、プラグイン・テーマ翻訳の世話役だったのですが、可搬 PC は持っていないし、子連れだし、遠方まで帰るために途中で抜けなければならないし、さらに、「Mac/Win で Poedit というアプリケーションを使う」というのが最も一般的と思われるのに自分では使っていないため[1]に操作方法を即答できない……、という幾重もの役立たずぶりですみませんでした。こどもの相手やら何やら、こちらのほうがお世話になりっぱなしで、ありがとうございました。

そういう中で質問を受けたことを、今さらながらここに書いておこうと思います。

翻訳作業のステップ

WordPress のプラグインやテーマの翻訳をやってみようという記事はあちこちにたくさんあります。ここでは細かく書きませんので、それらを参照してみてください。「POT ファイルとは何か」「PO ファイルとは何か」「それらはどこにあるか」などは既に知っているという前提で進めます。

おさらいです。WordPress のプラグインやテーマの翻訳作業のステップは

  1. プラグインやテーマのプログラムの中の翻訳されるべきメッセージに __() や _e() などのマークを付ける
  2. マークされた文字列を抽出して POT ファイルと呼ばれる、翻訳者にとって原本となるものを作成する
  3. POT ファイルを元に、メッセージをそれぞれの言語に翻訳した PO ファイル を準備する
  4. PO ファイルを編集する (これがほんとうの翻訳作業)

です。作業のスタート地点が後ろに近いほど、とっかかりやすいです[2]

最も始めやすい状態: ステップ4から

たくさんある記事のひとつ、Nao さんの「2014年版: WordPress プラグイン・テーマの翻訳を始めてみよう」を見てみます。

その記事にありますように、最も手軽に始められるのが、既に全部または一部翻訳がなされているものに対して、誤訳を修正するとか、別の訳語にするとか、訳の抜けている部分を補う、というものです。これなら最初のハードルがぐっと低く、ともかく「やってみよう」という気になれます。

Poedit なら、書き換えたい PO ファイルを開き、当該箇所を修正・加筆するだけです。

その次に楽な状態: ステップ3から

プラグインやテーマそのものは翻訳可能 (POT ファイルが用意されている) だが日本語訳 (name-ja.po) がない状態というのが、その次にとっつきやすい状態です。

公式ディレクトリに登録されているプラグインテーマなら「translation-ready」というタグが付けられているでしょう。ここでいうステップ1や2の処理が既にされているという意味です。

Poedit なら、「ファイル」-「POT ファイルを元に新しいカタログを作成…」で、「言語」に ja を指定して適切な名前 (name-ja.po の形) で保存します。

コマンドラインを使えるなら Poedit を使わずに、

msginit -i name.pot -o name-ja.po -l ja 

です。意味はなんとなくわかりますね。

この時点で、翻訳率0% の日本語翻訳ファイル name-ja.po ができます。

ステップ3をステップ4に

「0%」……嫌な響きですね。これだけでやる気が削がれてしまいます。なので、過去の資産から使えるものは少しでも流用します。

たとえばテーマの翻訳をしようとしているとします。その最初に、既存の、たとえばデフォルトテーマの twentyfourteen の翻訳を取り込んでしまおうというのです。

もしステップ3をコマンドラインでできたようなら、これまたコマンドラインで

msgmerge -o name-ja.po -C wordpress/wp-content/languages/themes/twentyfourteen-ja.po name-ja.po name.pot

のように、msgmerge を使います。-C で参考とする PO ファイルを指定します。-C はひとつのコマンドラインの中に何度でも指定できるので、WordPress 本体の ja.po や admin-ja.po も追加するといいかもしれません。

Poedit ではこれに相当する操作が簡単にできないようです。そこでステップ3の代わりに、次のようにします。name-ja.po がまだ存在しない状態で、参考とする PO ファイル (たとえば twentyfourteen-ja.po) を name-ja.po という名前でコピーします。これを Poedit で開き、「カタログ」-「POTファイルでカタログを更新…」します。

すると、英文が合致する分の翻訳がそのまま取り込まれます[3]。プラグインでは参考にする似たものを見つけてくることが難しいかもしれませんが、テーマの場合は、デフォルトのテーマを参考にしてうまくいけば80%ほども翻訳済みにしてしまうことができます。

これで、スタート地点をステップ3からではなく、ステップ4からにすることができます。

翻訳メモリ

Poedit には翻訳メモリという機能があります。データベースに登録しておけば、それを自動的に参照して、英文が合致する分を埋めてくれます。まずは WordPress 本体の ja.mo や admin-ja.mo それにデフォルトのテーマの twentyfourteen-ja.mo を登録しておきましょう。

これによってもスタート地点をステップ3からではなく、ステップ4からにすることができます。

前節の方法と翻訳メモリの方法は同時に使うこともできますので、積極的に翻訳メモリを使うのがいいでしょう。

といっても私自身が Poedit 自体(ということは翻訳メモリも)使っていませんので詳しく書けません。かなり古い記事ですが Tai さんの「poEditの翻訳メモリ機能を使う」や Miyoshi さんの「poEdit で翻訳ファイルを作る 」の「翻訳メモリを活用する」の節などを参考にしてください。

手抜きの効果

「手抜き」というと負のイメージの言葉ですが、ここではまったくそういうことはありません。むしろ用語の統一という点でも、積極的にここに書いた方法をとるべきだと思います。

そこで、最初掲げたステップを修正して、

  1. プラグインやテーマのプログラムの中の翻訳されるべきメッセージに __() や _e() などのマークを付けておく
  2. マークされた文字列を抽出して POT ファイルと呼ばれる、翻訳者にとって原本となるものを作成
  3. POT ファイルを元に、メッセージをそれぞれの言語に翻訳した PO ファイル を作る
    1. 過去の資産を参照して自動的に、できるだけ翻訳を埋める
  4. PO ファイルを編集する (これがほんとうの翻訳作業)

の赤い字の項目を必ず実行するように意識することを強くお奨めします。

ざっと検索してみた Poedit の使い方、WordPress の翻訳や WordPress 翻訳祭りのような WordBench などでの解説でも「POT ファイルから PO ファイルを作りましょう。空っぽの ja.po ができましたね。さあ翻訳を始めましょう」と、このあいだのステップが飛ばされているように思います。

いまからやろうとしている翻訳は、単語レベルでは既に誰かがやっているかもしれません。WordCamp Kansai 2014 のキーワードは「Share 分かちあい」でしたね。share できるものは share して、抜ける手はなるべく抜いて、その余力は別のところで活かしましょう。

これくらいの下調べは前もってやっておくべきでした。すみません。今後の各地のイベントや、あるいは個人で、翻訳やってみようかなというときには、前に書いた「WordPress 翻訳祭り—今さら注意してもらえない「日本語」について 」と併せて参考にしてもらえればと思います。

  1. ふだんは Debian 上の Emacs の po-mode で作業しています。
  2. このあと、それを開発者に送るとか、開発者の側では送られてきたものを最新版に合わせてからパッケージに同梱するとかの作業もありますが、ここでは省略します。それらとステップ2については以前「プラグインやテーマの国際化を少し楽に」に書きました。
  3. 合致しなかった部分を掃除するには Poedit では「カタログ」-「Purge Deleted Translations」です。