Rails勉強会@東京第3回に行ってきた。
集合
寝過ごしてしまって、シャワーを浴びて慌てて出掛ける。秋葉原に着くと、駅前で「完全メイド宣言」たらいうよくわからないグループが歌って踊り始めた。それを眺めながら参加者が集まるのを待つ。今回は参加者がちょっと少なめ。前回までと同じくオープンセッション方式を採った。
前半
前半は3つのテーブルに分かれた。私は、「自分は経験が無いのだけれど、誰か詳しい人、Railsの国際化について教えてください」と言って国際化のセッションを開いた。
- Railsのキャッシング
- Railsの国際化
- Special Generatorを読んでみよう
背景
さて、私がRailsの国際化なんて話題を取り出したのは、RoR日本語メーリングリストにちょっと前に流れた十河さんによる質問、[rails:934] ロケールによるテンプレートの切り替えによる。
私が今まで開発したアプリケーションは日本語だけ対応できればよかったのでjascaffoldがあれば十分だった。でも、将来性を考えて国際化対応というのは考えなくてはならない点だ。gettextというあたりがやはり有力な案だけれど、今回の十河さんのニーズにはマッチしなかった模様[rails:937]。
[rails:937]における十河さんのようなニーズは非常に現実的で、重要な問題だと思う。でも、Railsの国際化対応は色々あるらしいと聞きながらもあまり把握していなくて、適当なプラグインを作成はしてみたものの、正統なやりかたを知りたいと思った。それで、「誰か教えてほしい」とセッションを開いたのであった(hs9587メソッド)。
3つのやりかた
鈴木さんが前回までの国際化に関するセッションの結論を報告してくださった。今Railsの国際化対応として考えられている手法としては、gettextとGlobalizeプラグインが主流らしい。
さて、MVC構造のアプリケーションを国際化するにあたって3つのやりかたを考えられる。
- View層の差し替え
- 文言単位での対照訳
- Model, Controllerまで踏み込んだもっと奥深いやりかた
View層の差し替えはrailsではテンプレートファイルを差し替えるだけである。私が書いたプラグイン程度の簡単なものでも取り合えず使えるだろう。
gettextは「文言単位での対照訳」に相当する。これはそのままGNU gettextのruby版で、.moファイルから対照訳を取得する。
Globalizeは、Modelまで踏み込んだ「奥深いやりかた」だ。データベースに専用のテーブルを設けて翻訳情報などをそちらに格納する。
テンプレート差し替えには次のような利点がある。
- 比較的気軽に適用できる
- 速度は悪くない
- 国際化対応というのは異なる文化慣習への対応でもあるから、単なる文言の修正では済まないこともある。テンプレートごと差し替えてしまえばそういうケースでも対応が楽。
一方、欠点としては次のようなものが挙げられる
- 分離した各テンプレート間で修正を同期する問題
- テンプレートに流し込むデータのロケールについては、この手法単体では無力なケースがある。在庫表示における商品名とか。
gettextには次のような利点がある。
- デザイン(.rhtml)と翻訳(.po)の分業が容易
- 速い
- 情報が豊富。
- テンプレート差し替えには劣るが、後付けでの導入が容易
一方、gettextには次のような欠点がある
- 単なる文言の修正で済まないケースには無力
- データのロケールに付いてはテンプレート同様
Globalizeプラグインには次のような利点がある
- String#tがgettextと似たようなことをしてくれる。
- 違いは格納形式が.moではなくデータベースであることのみ。
Model層まで踏み込んだ細かなサポート。
- TimeクラスやNumericクラスを拡張して
localizeメソッドを定義。データベースに格納された設定にしたがって出力時のフォーマットを調整する。 - Modelについても翻訳をサポート。ActiveRecordを拡張し、翻訳対象に設定した属性はロケールごとに別々にデータを保存する。ビジネスロジックからは透過的にロケール依存のテキストを処理できる。
Locale.set("en-US") prod = Product.find(1) prod.name #=> "Meatballs" Locale.set("es-ES") prod = Product.find(1) prod.name #=> "Albóndigas"- TimeクラスやNumericクラスを拡張して
欠点としては
- 導入コストが高めかも。
- gettextと比べると重そう
- ドキュメントが少ない
実際、このセッションではここまでまとまった段階で「みんなで淡々とGlobalizeを試してみるよ」に以降したのだけれど、それぞれに引っかかって、時間内で動かせた人はいなかった。期待できるプロジェクトなのは確かである。けれども、情報豊富なgettextや、適当に書いてもそれなりに使えるテンプレート差し替えに比べると敷居が高いのは否めない。
GetText開発者から
2005-02-26追記。gettextのむとうさんからつっこみを頂いた。現実の開発ではテンプレート差し替えでは「修正時の同期の問題」が強く出てしまうという御意見。
文言だけ翻訳(snip)を強くオススメします。GetTextの歴史を考えても、多くのGUIアプリはこれで十分なはずです。
前述のテンプレート切替えプラグインの改良案も提示してくださった。
他のセッション
- Railsのキャッシング
- Rails内部のキャッシングについて調べたらしい。HTMLレベルでのキャッシングはしているようだけれど、DBクエリのキャッシングは不完全で、まだまだ改善の余地があるんではないかとのことらしい。
- Special Generatorを読んでみよう
- すごいのは生成のためのテンプレートであって、generatorとしては普通ということらしい。前提としてのscaffoldの中身の説明を詳しくやったらしい。
後半
2つのセッションに分かれた。
- はてなSNSの実装
- Rails/Rubyと全文検索
私ははてなSNSのほうに参加。id:secondlifeさんがRailsではてなSNSのクローンを作ったというので、そのソースコードを観賞する催し。約8時間で実装したという。
とりたてて派手な訳ではないけれど、モジュールがセンス良く切り分けられていて、勉強になった。
追記: みんなでid:secondlifeさんに「クローンも一般公開してよ」と言った。公開してくれたようだ。
いぬビームの中の人もいらしていて、クローンのほうに続いて、オリジナルのはてなSNSソースコードも観賞した。実に力強い実装であった。Ruby CGIプログラムにしてあのアクセス数をさばいているのは故無きことではない。
後半は、主にお二人のソースコードを題材に、参加者皆で「こんなライブラリがあればいいのに」を語った。
- Atomを透過的に扱えるRSSパーサーがあればいいのに
- ruby-feedparserがある。
- 正規表現にマッチする部分を抜き出して配列化するスマートな方法があればいいのに
- やっぱり今はgsub使ってる?
- UTF8にも対応している文字コード変換のスマートなAPIがあればいいのに。
- NKFはダサすぎ。-m0あたりは知らないとはまる
- KconvはUTF8に対応していない。APIは悪くない。
- Uconvなんてのもあったね
- Iconvは環境依存が痛い。APIダサい
- openuriがキャッシングなどもサポートしてくれればいいのに
- キャッシングをデフォルトで有効にすべきか、無効にすべきか設計が難しい。
- だったら別のメソッドにしてしまうのもアリか。
- require_dependencyは使える
懇親会
いぬビームの中の人と井上さんの間に座って、色々話した。いぬビームさんはお気に入りサジェスタといい、発想が素晴らしい人だ。
各ポータルサイトの実装を語ったりとか。Continuation萌えるよContinuationとか。
仕事でRails使ってますという人が段々増えてきた。私は、お客さんの目に触れるところにRails使った例としては割と早いほうらしいけれど、人の話を聞くにつれて「小規模システムだからやれたな」とか「うまくいったからいいけど、慎重さが足りなかったかも」とか痛感する。まぁ、無謀上等ということで。
コメント
こんにちは、nkfのメンテをやっている成瀬と申します。
まず枕に、
> 正規表現にマッチする部分を抜き出して配列化するスマートな方法があればいいのに
String#scanはいかがでしょう。
さて、
> UTF8にも対応している文字コード変換のスマートなAPIがあればいいのに。
まずnkfですが、元々の実装の都合上、
nkf = NKF.new
nkf.to = NKF::UTF8
nkf.from = NKF::SJIS
nkf.convert("ほげほげ")
なんてことができないので、
NKFはnkfの薄いラッパーであるべきだと考えており、
現状でしょうがないかなぁ、という気がしています。
#いや、不可能ではないですが、
#コードを見て想像されるような処理にはなりません。
Kconvは1.8.2以降でUTF-8に対応していますよ。
ただ、NKF以上に-m0ではまるのがネックだとも思っています。
この辺を回避可能な新しいAPIを追加してしまいたいと思いつつ、
<a href="http://www.rubyist.net/~matz/20060205.html#p03">http://www.rubyist.net/~matz/20060205.html#p03</a>
に言及されているI18Nも気になっていたりして。
ちなみに、1.9には試験的にKconv.convというメソッドを入れていて、
これでは比較的高度な指定ができるようにしてみたのですが、
自分で使っていて実装に失敗した感があるので、これは捨てる予定ですけれど。
よりよい案があれば、教えてくださると助かります。
#オプションをどう渡すか迷うんですよね。
成瀬さん、コメントありがとうございます。
> String#scan
存じませんでした。20人のRubyistが誰もとっさに思い出さなかったという…… (^^;
> nkf
まぁ、会場でそんな意見は出ましたということで。歴史的経緯からも、あれはしかたないんでしょうね。
> Kconv
これもUTF-8対応を存じませんでした。オプションはIconvでも苦心の後が見える様子でしょうか。1.9のKconvも拝見します。
遅ればせながら、議事録を公開していただきありがとうございました。
ローカライズ以外の部分も興味深く読まさせていただきました。