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