RailsでのContent Negotiationぽいもの。

[rails:934] に出てる、ApacheのContent Negotiationみたいな感じでテンプレートを切替えたいという需要。

Rails勉強会@東京での国際化対応を考えるセッションでは、やっぱりget_textを使うのがいいんでないのという結果だった筈。でも、この方は、なんか文言が長いからこれをget_textに掛けるのはやだなーと。

で、ApacheにおけるContent Negotiationみたいな感じで、適当にlocaleをsuffixに足してtemplateを探してくれたらうれしいよね、と言う話。実際、.rhtml, .rxmlの切替えはこれをやってる訳だもんね。

ぱっと思い付く案としては、 rails2uにあるやつ を応用するか。あとは、色々あるRails国際化対応プロジェクトのプロダクトを利用するか。

国際化対応プロジェクトはなんか色々で良く把握してないので、上のスレッドにどんなレスが付くものかちょっと楽しみにしていたけれど、回答が出てこないのね。質問者の方はググったけどよくわからんと仰ってるし。

うーん。調べてもよくわからんときは重複を恐れず適当に書いてみるが吉。DRYの心掛けも大切だけど、Don't be afraid to repeat someone else!

というわけで、Railsプラグインとして書いてみた。vendor/localize_templates/init.rbにこれを置くと、params[:locale]から持ってきた情報をsuffixにしてマッチするテンプレートを使用する。

ActionController::Base.class_eval do
  alias render_file_without_locale render_file
  private :render_file_without_locale

  def render_file_with_locale(template_path, status = nil, use_full_path = false, locals = {})
    locale_components = locale.split('_')
    until locale_components.empty?
      localized_path = template_path + "_" + locale_components.join('_')
      return render_file_without_locale(localized_path, status, use_full_path, locals) if template_exists? localized_path

      locale_components.pop
    end
    render_file_without_locale(template_path, status, use_full_path, locals)
  end
  alias render_file render_file_with_locale

  def locale
    params[:locale] or ''
  end
end

そういえば、rails内部ではこんな感じでaliasしてはwrapっていうのを幾重にもやってて、だからRailsの内部を読むとき、 前回の勉強会 でやったみたいに、action_controller/base.rbを追ってくだけだと実はカバーできない部分があるんだよね。例外時のフォローとか、filterとか。

でもなー、こういうテンプレート切替えって絶対どこかの誰かが書いてるよね。こういうのの正統なやりかたはどこだ。教えて、偉い人。