flash[:notice]の「ものぐさ」日本語化

Ruby-GetText はあれこれ言ったものの、やっぱり便利だ。ただし、インスタンス単位ではなくクラス単位でtextdomainがアサインされるようなので (間違ってたら失礼)、マルチスレッド環境下 (つまり通常の環境下) で正しく動くのかは不安だ。当面日本語だけしか出さないので問題は起こらないんだけど…。

out-of-the-boxの状態で (日本語で短くて適切な言い回しがわからん) も、かなり気持ちよい程度に日本語化されるんだけど、scaffoldとかが生成するflash messageは英語のままなので、こいつをとりあえず日本語化するための関数を作ってみた。今回のハイライトは恐怖の「verb_inflect」である。恐ろしく簡略化されているとはいえ、印欧語の末裔である英語を侮辱しすぎかもしれない。

module ActionController
  class Base
    def compose_completion_message(status)
      item = self.class.name.demodulize.sub(/Controller$/, '').underscore.downcase.singularize.gsub(/_/, ' ')
      case status
      when :success
        morpheme = params[:action].verb_inflect(:as => :past_participle)
        return _('%{item} is %{verb} successfully.') % {
          :item => _(item),
          :verb => s_("verb|#{morpheme}")
        }
      when :failure
        morpheme = params[:action]
        return _('Failed to %{verb} the %{item}.') % {
          :item => _(item),
          :verb => s_("verb|#{morpheme}")
        }
      end
    end
  end
end

つぎのように使えばよい。

flash[:notice] = compose_completion_message(:success)
flash[:notice] = compose_completion_message(:failure)

trueやらfalseやらを受け付けるようにしなかったのはセマンティクスの明示化*1のため。こういうクセは人によっては受け付けないだろう。困ったもんだ。

ちなみに、verb_inflect

class String
  def verb_inflect(options)
    capitalized = (/^[A-Z]*$/ =~ self)
    titlecased = !capitalized && (/^[A-Z]/ =~ self)
    verb = self.downcase
    verb = case options[:as]
      when :noun
        case verb
          when 'update'
            'update'
          # XXX: supply more entries for favorite verbs
          #       if you are really sure this works for you!!
          when /[^aeiou][aeiou]te$/
            verb[0...-2] + 'tion' # latin pp.
          when /[^aeiou][aeiou]$/
            verb[0...-1] + 'ing'
          else
            verb + 'ing'
        end
      when :preterite, :past_participle
        verb.sub(/e$/, '').sub(/([^aeiou])y$/, '\1i') + 'ed'
      when :gerund
        verb + 'ing'
    end

    verb.titlecase! if titlecased
    verb.upcase! if capitalized

    verb
  end
end

合掌。

追記: コードを張り付けてからバグが露呈したのでちょっと修正。

さらに追記: 一応上のは、DRYなものとRYなもののバランス感覚とは何かという問題提起のつもりでして。scaffoldだけに関して言えば、高橋さんのgettext-scaffoldを使うほうがいい。*2

*1:これまた日本語か?みたいな議論を喚起しそうな言葉だけど

*2:実は後で知った。けども誰か作ってるだろうとは思ってたので。