読者です 読者をやめる 読者になる 読者になる

gettextでSTIのカラム名もローカライズさせる

Ruby Rails

gettextはすごく便利なのですが、STIを使うと不具合があることがわかりました。
上のようなUser < Manager < Administrator
のような継承関係にあるモデルを用意します。
そして、

rake updatepo

して、sample.poを作成します。
中を見ると、
#: app/models/user.rb:-

msgid "User|Email"
msgstr "メールアドレス"

こんな感じにして、いつものように

rake makemo

してmoファイルを作成します。
そして、userモデルのerror_messages_forを見てみます。

すると、@userがUserクラスの場合は問題なく表示されるのですが、

@userがManagerクラスやAdministratorクラスの場合はカラム名は知らんぷりです。

STIを使って継承してモデルを作成すると、カラム名についてはそこまでgettext
考慮してくれないようです。
そのため、パッチを作成してみました。
このパッチを当てるとUser:Emailにロケールが無い時は、
Manager:Email、Administrator:Emailを探してくれます。

--- /opt/local/lib/ruby/gems/1.8/gems/gettext-1.10.0/lib/gettext/active_record.rb       2007-09-27 16:39:55.000000000 +0900
+++ vendor/plugins/gettext-1.10.0/lib/gettext/active_record.rb  2007-09-27 17:07:29.000000000 +0900
@@ -255,7 +255,7 @@
       if attr == "base"
         full_message = custom_msg
       elsif /%\{fn\}/ =~ custom_msg
-        full_message = custom_msg % {:fn => @base.class.human_attribute_name(attr)}
+        full_message = custom_msg % {:fn => sti_fn_of(attr)}
       elsif append_field
         full_message = @base.class.human_attribute_name(attr) + " " + custom_msg
       else
@@ -264,6 +264,20 @@
       full_message
     end
 
+    private
+    def sti_fn_of(attr)
+      klass=@base.class
+      while(klass!=klass.base_class)
+        fn=klass.human_attribute_name(attr)
+        if fn==attr
+          return fn
+        end
+        klass=klass.superclass
+      end 
+      return @base.class.human_attribute_name(attr)
+    end
+
+    public
     def localize_error_messages(append_field = true) # :nodoc:
       # e.g.) foo field: "%{fn} foo" => "Foo foo", "foo" => "Foo foo". 
       errors = {}

3日経って、武藤さんがこのブログに気づかなかったらメールしよう。