Play Framework / Scala 初めました。(*’-‘*)
2.3 系です(たぶん大事)。最初なので色々と細かなところで躓いています。主だったドキュメントに記載の無いようなこともあったりしましたので、この記事に備忘録的な感じで記録しておきます。
なお、この記事はしばらくは覚えた事を少しずつ追記しますー。
Play Framework / Scala 初めました。(*’-‘*)
2.3 系です(たぶん大事)。最初なので色々と細かなところで躓いています。主だったドキュメントに記載の無いようなこともあったりしましたので、この記事に備忘録的な感じで記録しておきます。
なお、この記事はしばらくは覚えた事を少しずつ追記しますー。
WordPress などの情報で、いつも参考にさせて頂いている串本の宮さん(イケメン)のブログで「WordPressでget_*()を使うときは念のためソースを確認して適切に処理すべし!」というお話があって「 (^・0・^。) ホー」となったので、難しいことはあまり気にせずに the_*() 関数の値を文字列として取得できるユーティリティ関数を書きました。
これです。
1 2 3 4 5 6 7 8 9 10 |
if ( ! function_exists( 'get_the' ) ) { function get_the( $func ) { $func = 'the_' . $func; $args = func_get_args(); array_shift($args); ob_start(); call_user_func_array( $func, $args ); return ob_get_clean(); } } |
Gist にもアップしておきました。 https://gist.github.com/yuka2py/8698134
functions.php に上のコードを足したら使えるようになります。
使い方は次のような感じです。the_* 関数の「*」にあたる部分の名前をこの関数に与えてください(the_permalink 関数の出力値を取りたい時には、the_ を除いた permalink のみを与えます)。
1 2 3 |
<?php $permalink = get_the('permalink'); |
誰かのお役にたったらいいなぁー。 (*’-‘*)
立たないかな〜。
引数を取る the_*() 関数があったかな?
あったら引数も取れるようにしますので、ご指摘ください。引数無い方が少ないってご指摘いただいたので、引数対応しておきました。 (^_^;A
毎日のように新しい技術が聞こえてきて、去年覚えたことの幾つかは、今頃はもう古い何かの一つになってしまって、頑張って追いつこうとしても何だか少しずつ離されていくような気がして、だからいつもどこか初心者な気持ちがして、同じ年頃の人にも、僕よりずっと若い人たちにも、自分よりもずっと色々なことを知ってる人が沢山いて、だから時々不安になったりもして、落ち着かない気持ちになったりもする。
ねぇ、僕はだいじょうぶかな?
§
年が明けてすぐのある夜。僕は妻と一緒にライブハウスで音楽を聴いていた。演者の多くは知らない人たちだったけれど、演奏もパフォーマンスも素晴らしくって、僕らは少しお酒を飲んで、その時間をとても楽しんで、そしてふと気づいた。「演奏しているアーティストは皆とても楽しそうだな」と。
僕はエンジニアである。こんなふうに、僕は毎日の仕事を楽しめているだろうか?
「いやほら、僕らは地味な仕事だよ。スポットライトも無いし、ファンも居ないし、音楽をやってる人たちとは違うよ。あの人たちは自分を音楽で表現してるんだよ。でも僕らは要求仕様をカタチにするだけだから、ぜんぜん違うよ。僕らの仕事は……」
「…そうなの?」
演奏を楽しむステージの上のアーティストを見ながら、僕は否定した。
僕は自分が仕事を「楽しめている時」を思い出してみる。新しいコードをどう書こうか考えている時。もう少し良いコードにならないか?と試行錯誤している時。そしてそれが決まった!時。面白そうな技術をちょっと予習してみて「アレに使ったらスゴイんじゃない?」と妄想した時。お客さんに納品して感謝された時。そして実は隠しておいたオマケ機能に気づいてもらって感動してもらった時…。
そうだよ。僕らの仕事も素敵ことがいっぱいじゃないか。
ミュージシャンに光でいっぱいのステージがあるように、僕らには僕らが持ってる技術を発揮できるプロジェクトがある。ひとつひとつのプロジェクトが僕らのステージだ。ただ「こなして」たら楽しくない。どのプロジェクトでも、自分の技術を存分に発揮して、僕らはコードを書いて、まず自分が楽しんで感動したら良いんだ。そこから自然に新しい目標やモチベーションが生み出されるだろうし、技術も追いついてくるだろう。
忘れたらダメなことは、僕らの仕事も創造であり芸術であるということ。大切なことは、だから僕らは楽しむことが出来るし、楽しむことでこそ自分の未来が広がって行くんだろうということ。そして気づくべきことは、もし僕らに死が訪れるとしたら、それは自分自身の仕事に感動できなくなった時だろうということ。
歌を歌うように。音を奏でるように。
僕はエンジニアだ。そして僕は今も、スポットライトの中にいるんだ。
§
クライベイベー EG MVの・ようなもの
本文のようなことを考えさせてくれたアーティストの一人、EG さんの「MVの・ようなもの」です。生きてると、状況が良い時も悪い時も色々あるだろうけれども、僕はどんな時もそれを受けとめて、こんなふうに仕事をして行きたい。そして僕は僕がエンジニアである限り、いつも自分自身が感動できるような仕事を積み重ねて行きたいです。それはきっと僕のため、お客さんのため、そしてこの世界の為になるだろうと。
新年の挨拶にかえての・ようなもの 。
§ 2014-1-13 追記
今も皆さんに読んでいただいているので、少しだけ追記。この文章を書いた動機の一つに、次の記事がありました「WEBデザイナーが死ぬ時」。ここに書かれてあることは、僕も少なからず感じていたことだったけれど、こんな風に恐怖を抱えて生きていたくは無い、とも思ってました。僕らにとって技術はとても大切だけれども、僕らが創造できる価値は、技術だけでは生み出せない筈です。すごい技術者さんも、自称普通の人も、そうでない人も、技術が好きなら大丈夫だと僕は思っています。技術が好きなら、自然と努力もしてるだろうし、自分の明日を広げていけるはずではないかと。
HTML5 では section 要素が導入され、これまでの見出し要素(h1〜h6)のみによる大雑把なドキュメントアウトラインの形成に伴う諸処の問題を、明示的に分かりやすく解決・表現できるようになりました。しかし一方で、見出し要素(h1〜h6)を使った暗黙的なセクショニングも併用することが可能であり、これが人間にとって理解しにくいドキュメントアウトラインを形成することもあります。
例えば次のマークアップの例は、
1 2 3 4 5 6 7 8 9 |
<h1>あああ</h1> <h2>いいい</h2> <h3>ううう</h3> <h4>えええ</h4> <section> <h5>おおお</h5> <h1>かかか</h1> </section> <h6>ききき</h6> |
次のアウトラインを形成します。
1 2 3 4 5 6 7 |
1. あああ 1. いいい 1. ううう 1. えええ 2. おおお 3. かかか 4. ききき |
どうでしょうか?
もしこれに違和感があるようでしたら、まだ理解が不足していると思います。
実は僕もついちょっと前まで大事な部分を誤解していたのですが、先日参加させて頂いた「MarkupCafe Osaka Vo.1」で、松田さん(@matsudasu)とこのあたりで議論になったことがきっかけで、ようやく改めて理解できた感じです(松田さんには Facebook 上で一緒に考えたり、議論をしたり、色々教えて頂いたりして大変勉強になりました!サンクスです!)。
そこで本稿では、HTML5 のセクショニングとアウトラインアルゴリズムについて、僕が個人的に理解が不足していた箇所を中心に、なるべく分かりやすく解説してみたいと思います。
なお、本稿はアウトラインアルゴリズムについての補足であり、セクショニングコンテンツやセクショニングルート、また明示的・暗黙的セクションに関しての基本的な解説は含みません。必要に応じて、次のリンク先や、他の関連コンテンツを参照してください。
— HTML5 ドキュメントのセクションとアウトラインhttps://developer.mozilla.org/ja/docs/Web/HTML/Sections_and_Outlines_of_an_HTML5_document
— 見出しとセクション
http://www.html5.jp/tag/elements/headings-and-sections.html
また、本稿での例やその他の例のアウトラインを確認したい場合には、次のサイトが便利です。マークアップが実際にはどんなアウトラインを形成するのか、自分で試してみるととても面白い発見があると思います。
— HTML 5 Outliner
http://gsnedders.html5.org/outliner/
セクションの中の「最初の見出し要素」は、そのセクションの見出しになります。見出し要素は h1 〜 h6 のどれでも構いません。
1 2 3 4 |
<h2>あああ</h2> <section> <h3>いいい</h3> </section> |
この時、<h3>いいい</h3> は、それを囲った <section> の見出しになります。また、形成されるアウトラインは次のようなものになります。
1 2 |
1. あああ 1. いいい |
【重要】ここで <h2>あああ</h2> は、HTMLには書かれいない body 要素(セクショニングルート)の見出しになっています。この後の例でも、body 要素を省略していますが、意味的には必ず body 要素があるものとして読み取ってください。
簡単なようですが、では、次のマークアップではどのように解釈できるでしょうか?
1 2 3 4 5 |
<h2>あああ</h2> <section> <h3>いいい</h3> <h3>ううう</h3> </section> |
section 内の最初の見出し要素 <h3>いいい</h3> が section の見出しになるのであれば、次の <h3>ううう</h3> はどうなるでしょうか? h3 が連結されて <h3>いいいううう</h3> という意味合いになるでしょうか? あるいは、2個目のセクションは1つ深い階層のアウトラインとなるでしょうか?
正解は次のマークアップと同じ意味になります(分かりやすさの為に、暗黙的に作られたセクション [section] と表記してみました)。
1 2 3 4 5 6 7 |
<h2>あああ</h2> <section> <h3>いいい</h3> [/section] ← 暗黙的にセクションが終了し [section] ← 再開される <h3>ううう</h3> </section> |
明示的に開始されたセクションの見出しが最初の <h3> になるので、次の同じ <h3> のタグが現れた時点で、セクションは暗黙的に終了して同じレベルで再開されます。
では、次の例ではどうでしょうか?
1 2 3 4 5 |
<h2>あああ</h2> <section> <h3>いいい</h3> <h4>ううう</h4> </section> |
これは素直に次のようなアウトラインを形成します。
1 2 3 |
1. あああ 1. いいい 1. ううう |
さて、では次の例ではどうでしょうか?
1 2 3 4 5 |
<h2>あああ</h2> <section> <h3>いいい</h3> <h1>ううう</h1> </section> |
この場合、アウトラインは次のようになります。
1 2 3 |
1. あああ 1. いいい 2. ううう |
セクションの見出しとなった <h3> に比べて、より高いレベルの見出し要素 <h1> が指定された為、明示的なセクションは一旦終了して再開されます。但し、見出し要素による暗黙的なセクショニングは、あくまでも明示的なセクションの中に限ってのものです。ですから、<section> タグを超えることはなく、同じレベルでセクションを再開します。
分かりやすくするために、また [section] という表記を使って、暗黙的に作られたセクションを表してみます(なお、この記法では見出し要素の番号(レベル)は意味が無くなるため、以降、見出し要素の番号の表記を省略します)。
1 2 3 4 5 6 7 |
<h_>あああ</h_> <section> <h_>いいい</h_> [/section] [section] <h_>ううう</h_> </section> |
暗黙的なセクションが明示的なセクションを超えていないことが理解できると思います。
では、さらに次の例はどうでしょうか?
1 2 3 4 5 6 7 8 9 |
<h4>あああ</h4> <section> <h6>いいい</h6> <h3>ううう</h3> <h4>えええ</h4> <h2>おおお</h2> <h5>かかか</h5> <h1>ききき</h1> </section> |
これは次のアウトラインを形成します。
1 2 3 4 5 6 7 |
1. あああ 1. いいい 2. ううう 1. えええ 3. おおお 1. かかか 4. ききき |
複雑なようですが、ここまでのお話で理解できる筈です。暗黙的セクションを [section] として表すと、これは次のように解釈されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<section> <h_>いいい</h_> [/section] [section] <h_>ううう</h_> [section] <h_>えええ</h_> [/section] [/section] [section] <h_>おおお</h_> [section] <h_>かかか</h_> [/section] [/section] [section] <h_>ききき</h_> </section> |
見出し要素による暗黙的セクションでは、例えば次のように番号を飛ばして表記することが出来ますが、
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<h1>あああ</h1> <h2>いいい</h2> <h3>ううう</h3> <h1>かかか</h1> <h3>ききき</h3> <h6>くくく</h6> <h1>さささ</h1> <h3>ししし</h3> <h2>すすす</h2> <h3>せせせ</h3> <h4>そそそ</h4> |
セクションの階層は常に1段階ずつなので、 次のようなアウトラインを形成します。
1 2 3 4 5 6 7 8 9 10 11 |
1. あああ 1. いいい 1. ううう 2. かかか 1. ききき 1. くくく 3. さささ 1. ししし 2. すすす 1. せせせ 1. そそそ |
3つの例がありますが、2番目の例のように、h1 から h3 に飛んでもアウトラインは1階層深くなるだけです。また、3つ目の例のように、<h3>ししし</h3> と書いても階層は1つ深くなるだけなので、次の行の <h2>すすす</h2> は同じレベルで開始されます。このように、見出し要素の番号を飛ばして書いても、アウトラインの階層は常に1階層ずつ深くなることに注意が必要です。
最後に、ここまでの理解を踏まえて、最初の例について考えてみます。
1 2 3 4 5 6 7 8 9 |
<h1>あああ</h1> <h2>いいい</h2> <h3>ううう</h3> <h4>えええ</h4> <section> <h5>おおお</h5> <h1>かかか</h1> </section> <h6>ききき</h6> |
上の例は、次のアウトラインを形成しました。
1 2 3 4 5 6 7 |
1. あああ 1. いいい 1. ううう 1. えええ 2. おおお 3. かかか 4. ききき |
順番に考えてみましょう。分かりやすさの為に、暗黙的セクションを [section] と表記します。なお、セクショニングルートとして body タグがあることを忘れないで確認してください。
さて、まず、最初の <h1>あああ</h1> から <h4>えええ</h4> は次の通りになると思います。
1 2 3 4 5 6 7 |
<h_>あああ</h_> [section] <h_>いいい</h_> [section] <h_>ううう</h_> [section] <h_>えええ</h_> |
これは単純ですね。
さて、<h4>えええ</h4> の後に <section> が来ますので、「暗黙的セクションは明示的セクションを超えられない」ので、全ての暗黙的セクションが終了します。
1 2 3 4 5 6 7 8 9 10 11 |
<h_>あああ</h_> [section] <h_>いいい</h_> [section] <h_>ううう</h_> [section] <h_>えええ</h_> [/section] [/section] [/section] <section> |
次に明示的セクションが開始されます。ここで、h5 が明示的セクションの見出しになりますね。
1 2 3 4 5 6 7 8 9 10 11 12 |
<h_>あああ</h_> [section] <h_>いいい</h_> [section] <h_>ううう</h_> [section] <h_>えええ</h_> [/section] [/section] [/section] <section> <h_>おおお</h_> |
次に <h1>かかか</h1> ですね。明示的セクションの見出し要素となった h5 よりも上の見出しレベルなので、明示的に開始されたセクションは、暗黙的に一旦終了して再開されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<h_>あああ</h_> [section] <h_>いいい</h_> [section] <h_>ううう</h_> [section] <h_>えええ</h_> [/section] [/section] [/section] <section> <h_>おおお</h_> [/section] [section] <h_>かかか</h_> </section> |
最後に <h6>ききき</h6> が新しいセクションを開始します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<h_>あああ</h_> [section] <h_>いいい</h_> [section] <h_>ううう</h_> [section] <h_>えええ</h_> [/section] [/section] [/section] <section> <h_>おおお</h_> [/section] [section] <h_>かかか</h_> </section> [section] <h_>ききき</h_> [/section] |
このように、順序だてて見て行くと、ある程度理解も容易になると思います。
もし「難しいな」と思うようであれば、それは見出し要素(h1〜h6)の番号に惑わされ過ぎなのかも知れません。「見出し要素の番号はアウトラインの階層を表すものでもなく、単に相対的な位置づけを表しているに過ぎない」ぐらいに思うと、より分かりやすくなるのではないかと思います。
ここまでに見て来たように、明示的セクションと暗黙的セクションを合わせて利用するときには、いくつかの留意すべき点があり、それを誤ると、マークアップから直感的に理解できるアウトラインと、実際のアウトラインとが乖離してしまうことになります。
個人的には、以下のような点を理解していたら迷うことは無いのではないかと思っています。
また、よく言われることですが、実務では以下のような方針を取ると、混乱が減らせて良いのではないかと思います。
以上です。
もし何か誤った解釈などがありましたら、ご指摘いただけると嬉しいです。
WordPress 3.7 から、コアやプラグインの自動アップデートの仕組みが準備され、今後言語ファイルのアップデートも自動化されることにると思います。2013 年 10 月 28 日現在、まだその準備段階にあるようですが、関連して今後おそらく、言語ファイルのロード方法が変わるようになります。では、今日現在、プラグイン作者はどのようにしておくのが適切なのかをちょっと考えてみました。
なお、今後の言語ファイルの管理全体がちょっと見えていないので、認識不足や間違いがあればご指摘頂けると嬉しいです。
WordPress 3.6 以前は概ね次のような記述だったと思います。
1 2 3 4 5 6 |
add_action( 'plugin_loaded', function() { load_plugin_textdomain( 'mytextdomain', false, 'myplugin/languages'); } add_action( 'after_setup_theme', function () { load_theme_textdomain( 'mytextdomain', get_template_directory() . '/languages' ); } |
どちらも言語ファイル(.mo)の場所をパスで指定しています。プラグインは相対パス、テーマは絶対パスでの指定と、ちょっと一貫性がなくてややこしかったですね。
WordPress 3.7 以降で、言語ファイルを自動アップデートを適用する場合、次のような記述になるようです。
1 2 3 4 5 6 |
add_action( 'plugin_loaded', function() { load_plugin_textdomain( 'mytextdomain' ); } add_action( 'after_setup_theme', function () { load_theme_textdomain( 'mytextdomain' ); } |
テキストドメインだけの記述になり、簡潔になりました。これはしっくり来て良いですね。
ではどのように .mo ファイルの場所が特定されるかというと、新しい規定のルールが導入され、それぞれ WordPress 内の次の場所に置かれることになります。
この場所へどうやってデプロイするのか、まだ僕は見つけれていません (^_^;A が、おそらく準備中なのかなーと思っています。
さて、翻訳フォイルを上記の場所にデプロイできる環境が整ってそこの言語ファイルを配置できたら、WordPress 3.7 以降をインストールしている環では言語ファイルの自動アップデートが適用されます。また、開発者視点では、言語ファイルの追加や修正でプラグイン自体をアップデートする必要も無くなる改善です。しかし、次の課題があります。
では、現時点でどう対処するのが良いかというと、現時点では次の感じかなーと思っています。
1 2 3 4 5 6 7 8 |
add_action( 'plugin_loaded', function() { load_plugin_textdomain( 'mytextdomain' ) or load_plugin_textdomain( 'mytextdomain', false, 'myplugin/languages'); } add_action( 'after_setup_theme', function () { load_theme_textdomain( 'mytextdomain' ) or load_theme_textdomain( 'mytextdomain', get_template_directory() . '/languages' ); } |
load_plugin_textdomain()、load_theme_textdomain() のいずれの関数もロード出来なかった場合に false が変えるので、まず新しい仕組みでロードし、失敗して false が返ってきた場合にこれまでの方法でロードします。
これで新しい仕組みで言語ファイルを提供できるようになった段階で、リリースしているプラグインやテーマは自動的に新しい言語ファイルを参照するようになるように思います(おそらく・たぶん…というかこの辺り、運用上の実際の計画や具体的な更新の仕様が見えていななくてちょっと心配。情報が見つけられないでおります…)(直子さんがしっかり情報をまとめてくださっていました 。本稿では実装面のお話をさせて頂きましたが、全体の背景、今後についてなどは次のリンク先の直子さんの記事をご覧ください。http://ja.naoko.cc/2013/10/28/wordpress-37-background-update/ )。
当然ながら、これまで同様にプラグインやテーマに言語ファイルを同梱する必要がありますが、過渡的には仕方ないかなーと思います。そして、新しい仕組みの運用体制が十分に安定したら、3.6 以前の環境には言語ファイルの追加・更新を提供しない、というポリシーとするのが妥当かと思います。
おまけというか、実はここからが書きたくてこのこの記事を書いたのが本音です。 (*’-‘*)
WordPress 3.7 の load_plugin_textdomain() の実装ですが、次のようになっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
function load_plugin_textdomain( $domain, $deprecated = false, $plugin_rel_path = false ) { $locale = get_locale(); /** * Filter a plugin's locale. * * @since 3.0.0 * * @param string $locale The plugin's current locale. * @param string $domain Text domain. Unique identifier for retrieving translated strings. */ $locale = apply_filters( 'plugin_locale', $locale, $domain ); if ( false !== $plugin_rel_path ) { $path = WP_PLUGIN_DIR . '/' . trim( $plugin_rel_path, '/' ); } else if ( false !== $deprecated ) { _deprecated_argument( __FUNCTION__, '2.7' ); $path = ABSPATH . trim( $deprecated, '/' ); } else { $path = WP_PLUGIN_DIR; } // Load the textdomain according to the plugin first $mofile = $domain . '-' . $locale . '.mo'; if ( $loaded = load_textdomain( $domain, $path . '/'. $mofile ) ) return $loaded; // Otherwise, load from the languages directory $mofile = WP_LANG_DIR . '/plugins/' . $mofile; return load_textdomain( $domain, $mofile ); } |
これって、次のようにした方が良いと思うんですよね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
function load_plugin_textdomain( $domain, $deprecated = false, $plugin_rel_path = false ) { $locale = get_locale(); /** * Filter a plugin's locale. * * @since 3.0.0 * * @param string $locale The plugin's current locale. * @param string $domain Text domain. Unique identifier for retrieving translated strings. */ $locale = apply_filters( 'plugin_locale', $locale, $domain ); //Prepare mofile name $mofile = $domain . '-' . $locale . '.mo'; //Try load from the languages directory $path = WP_LANG_DIR . '/plugins'; if ( load_textdomain( $domain, $path . '/' . $mofile ) ) return true; //Otherwise, load from the legacy filesystem if ( false !== $plugin_rel_path ) { $path = WP_PLUGIN_DIR . '/' . trim( $plugin_rel_path, '/' ); } else if ( false !== $deprecated ) { _deprecated_argument( __FUNCTION__, '2.7' ); $path = ABSPATH . trim( $deprecated, '/' ); } else { $path = WP_PLUGIN_DIR; } return load_textdomain( $domain, $path . '/'. $mofile ) ); } |
要するに、新しい仕組みでのロードを先に行うということなのですが、こうしておくとコードの変更無しに、運用で順次新しい仕組みが適用していけた筈なのですが、どうしてこうなって無いのかなーと疑問に思ってしまうわけです。
どなたか理由を知っていたら教えて頂けたら嬉しいです。
(参考URL)
http://ottopress.com/2013/language-packs-101-prepwork/