よたらぼ
自分の興味の赴くままにIT技術系のネタを取りとめもなくメモっています。
Ruby言語やLinuxのネタが多いです。

October 22, 2007 [おもひで]

[Rails] STIなモデルを翻訳対象にする

Ruby-GetTextを使って、STIモデルが翻訳できないという指摘があったのですが、これはバグではなく仕様です。

具体的にはSTIなモデルで(updatepoで)テーブル名・カラム名を翻訳対象にしたいという場合は以下のように"ActiveRecord::Base"の文字列をファイル中に記述します。

 class Manager < User   # ActiveRecord::Base
 end

こうすることでManagerモデルのテーブル名・カラム名がmsgidとして抽出されるようになります。あとは通常どおり翻訳するだけです。
updatepoタスクでは、ActiveRecord向けにmsgidを抽出をする際に、そのファイル中に"ActiveRecord::Base"があればそれはActiveRecord::Baseのサブクラスのファイルである、とみなします。
したがって直接継承関係が無くても上記のように記述するわけです。

より詳しい情報はruby-gettext-MLのログを参照してください・・・・と思ってrubyforgeのMLログ見たら文字化けしてる・・・(ここでもsfmltojが必要か!? 昔は日本語通ったと思うんだけどなぁ、うーん)。一応、一月分のログなら見れるようです。こちらでsti-sampleと検索してみてください

[Rails] STIなモデルを翻訳対象にする(2)

MLが読みづらいのでここに整理しておきます。問題の指摘内容を整理すると、

「Manager < User < ActiveRecord::Baseという関係のクラスがある(Userはemailというカラムを持つ)。

rake updatepoするとUserのみが翻訳対象になり、Managerは翻訳対象にならない(1)。

User|Emailは翻訳されるけど、Manager|Emailは翻訳されない。

UserモデルにUser|Emailが定義されているんだからそのサブクラスであるManagerモデルではManager|Emailが無い場合はUser|Emailが翻訳文字列として使用されるべき(2)」

の2点です。

まず、(1)ですが、これは上で述べた方法で回避します。厳密に言えば今のrgettextが力不足で、上記のような指定をしなくても翻訳文字列として抽出できるというのがベターなのですが、なかなかうまい実装が思いつかないのが現状です。

(2)ですが、GetTextの考え方で言うと、Manager|EmailとUser|Emailは本来別の意味を持ち、分けて考えるべきです。例えば、User|Emailは「Eメールアドレス」と訳すかもしれませんが、Manager|Emailは「管理者Eメールアドレス」と訳すかもしれません。

さて、Ruby-GetText-Packageは、国際化ライブラリの一つでメッセージをローカライズするというのが主目的のライブラリです。Railsを使う人の多くは自国だけのアプリを作るためにRuby-GetText-Packageを使っている人が多いのであまり意識されないのかもしれませんが、ここで開発者以外の「翻訳者」という登場人物を考える必要があります。

翻訳者は、poファイルだけを見て(アプリの実装を知らずとも)翻訳作業を行います。その時に、開発者が(翻訳対象が減る=DRY!という観点から)poファイルにManager|Emailを無くしてしまうとすると、翻訳者は訳すどころかManager|Emailの存在すら知ることができません。もちろん、アプリケーションの内部まで追ってManager|Emailが定義されていないことを発見するという強者の翻訳者もいるかもしれませんが、私が翻訳者だったら、

「なんだか思ったとおりの訳にならないけど、まぁ、いっか、そのままで。」

と考えてそこで終わりにすると思います。せっかく適切な訳にできる余地があるのに残念な結果になってしまうかもしれません。

Emailなんだからどこの国でも訳語は1つしかないよ、と思うかもしれませんが、国によっては訳したいポイントが違うかもしれませんので、そこは開発者自身の文化的背景だけで決めたりせず、翻訳者に委ねるべきでしょう。

したがって、Ruby-GetText-Packageというライブラリとしてはアプリケーション作者がManager|Emailを用意せざるを得ない環境を作る、というのが正しい方向性で、「なかったらUser|Emailを使ってしまう」というのは目指す方向性が違う訳です。


編集