自動Gettext

Amrita2にGettextと連動する機能を実装しました。これを利用すると、ビューを最小限の手間で国際化することができます。

サンプルとして LoginEngineをAmrita2化+日本語化していますが、たとえば、homeというビューは次のようになります。

元のrhtmlのファイルは次のようなものです。

<div title="<%= title_helper %>" class="memo">
  <h3>Welcome</h3>
  <p>You are now logged into the system, <%= @fullname %>...</p>
  <p>Since you are here it's safe to assume the application never called store_location, otherwise you would have been redirected somewhere else after a successful login.</p>

  <%= link_to '&#171; logout', :action => 'logout' %>
</div>

これをAmrita2のAmXML形式に書き直すと、こうなります。

<<div class="form":|Attr[:title=>:title_helper]<
  <<h3<
    Welcome
  <<p<
    <% $_ = { :name => @fullname } %>
    You are now logged into the system,  %{name} ...
  <<p<
    Since you are here it's safe to assume the application never called store_location,
    otherwise you would have been redirected somewhere else after a successful login.

  <%= link_to '&#171; ' + _('logout'), :action => 'logout' %>

Rakefileに次のようなタスクを追加して、これを実行します。

task :updatepo do
  $: << 'vendor/plugins/amrita2/lib'
  require 'gettext/utils'
  require 'amrita2/gettext'
  require 'amrita2/macro'
  GetText.update_pofiles("login_engine", #テキストドメイン名(init_gettextで使用した名前)
                         Dir.glob("{app,config,components,lib}/**/*.{rb,rhtml,a2html}"),  #ターゲットとなるファイル
                         "logine_engine 1.0.0"  #アプリケーションのバージョン
                         )
end

すると、*.a2html形式のファイルに対して、Amrita2で追加したパーサが起動して、poファイルができます。これをja/*.potにコピーして、日本語を入れていきます。

potファイルから上記のビューに関連する所だけ抜き出すと

#: app/views/user/home.a2html:-
msgid "Welcome"
msgstr "ようこそ"

#: app/views/user/home.a2html:-
msgid ""
"Since you are here it's safe to assume the application never called "
"store_location,\n"
"    otherwise you would have been redirected somewhere else after a "
"successful login."
msgstr ""
"この画面が表示されるのはアプリケーションが store_location を呼んでないからで"
"す。呼んでいれば、ログインに成功した後には、他の画面にリダイレクトされるで"
"しょう"

#: app/views/user/home.a2html:-
msgid "You are now logged into the system,  %{name} ..."
msgstr "%{name}さん、あなたはこのシステムにログインしています。"

#: app/views/user/home.a2html:-
msgid "logout"
msgstr "ログアウト"

後は、以下のページにあるように通常通りの作業をすればOKです。

結果、次のように表示されます。

<div title="UserController home" class="form">
  <h3>ようこそ</h3>
  <p>  中島 拓さん、あなたはこのシステムにログインしています。</p>
  <p>この画面が表示されるのはアプリケーションが 
     store_location を呼んでないからです。呼んでいれば、
     ログインに成功した後には、他の画面にリダイレクト
     されるでしょう</p> 
  <a href="/user/logout"><<ログアウト</a> 
</div>

ポイントは、以下の通りです。

  1. ビュー内の文字列は全て自動的にGettext対応の文字列として抜き出す
  2. 可変部分の埋めこみもほぼ自動的
  3. erb形式との混在が可能

順番に説明していくと

  <<h3<
    Welcome

"Welcome"という文字列が自動的にpoファイルに抽出されています。

  <<p<
    <% $_ = { :name => @fullname } %>
    You are now logged into the system,  %{name} ...

<% ... %>内には、自由にRubyの処理を記述できます。各文字列は、内部的には以下のようなRubyソースにコンパイルされますから、この中で $_ にハッシュを設定することで、可変部の埋め込みが行われます。

    stream.concat _("You are now logged into the system,  %{name} ...") % $_

これを次のように書くこともできます。

  <<p:|ToHash[:name=>:fullname]<
    You are now logged into the system,  %{name} ...

なお、最初からAmrita2のテンプレートを想定して、コントローラ側でデータ構造をうまく設定すれば、このような処理( $_ への値の設定)は不要になります。

<%=....%>の中に翻訳すべき文字列がある場合には、一般のrhtmlファイルと同じように、文字列を_(...)で囲みます。

  <%= link_to '&#171; ' + _('logout'), :action => 'logout' %>

ビュー内の静的な文字列が特別な手間をかけることなく全て自動的に国際化されるので、アプリケーションによっては効果が大きいのではないかと思います。