Rails2.2の新機能i18nを使ってみる

このエントリーを含むはてなブックマーク

はじめに

Rails2.2ではついに国際化が標準で搭載されることになった。

Rails 2.2 リリースノート日本語訳

これまでRuby on Railsで作ったアプリの検証メッセージなどを日本語化する場合は gettextを使う方法がデファクトスタンダードだったけれど、正直めんどくさいし、初心者にはとっつきにくかった。

ということで正式版が登場する前にi18nを試してみよう。

準備

まずはプロジェクトを作成してedge版を展開する。

  1. % rails sample
  2. % cd sample
  3. % rake rails:freeze:edge


次に必要なプラグインをインストールする
localized_datesとi18nを入れる。

http://github.com/clemens/localized_dates/tree/master
http://github.com/mattetti/i18n/tree/master

  1. % script/plugin install git://github.com/clemens/localized_dates.git
  2. % script/plugin install git://github.com/svenfuchs/i18n


次にi18nを初期化してロケールファイルを読み込む処理を用意
config/initializers/init_i18n.rb
というファイルを作成して

  1. I18n.default_locale = 'ja-JP'
  2. LOCALES_DIRECTORY = "#{RAILS_ROOT}/config/locales/"
  3. LOCALES_AVAILABLE = Dir["#{LOCALES_DIRECTORY}/*.{rb,yml}"].collect do |locale_file|
  4.   File.basename(File.basename(locale_file, ".rb"), ".yml")
  5. end.uniq.sort


を記述する。

デフォルトのロケールを日本語にしてconfig/locales/以下にあるロケール名.rb、ロケール名.ymlを読み込む。

次にロケール用のファイルを用意する

  1. touch config/locales/ja-JP.rb
  2. touch config/locales/ja-JP.yml


サンプルアプリをscaffoldで作成する

日本語化の準備ができたのでサクっとscaffoldでメモ帳など作ってみよう。

  1. % script/generate scaffold note title:string body:text


app/models/note.rbを編集する

  1. # app/models/note.rb
  2. class Note <ActiveRecord::Base
  3.   validates_presence_of :title, :body
  4.   validates_uniqueness_of :title
  5. end


確認

ではサーバを起動して確認してみよう

  1. % rake db:migrate
  2. % script/server


失敗

失敗

失敗。
翻訳が見つからないそうだ。

config/locales/ja-JP.rb

を以下のように編集して、基本的な翻訳メッセージを用意してやる。

  1. {
  2.   :'ja-JP' => {
  3.     # date and time formats
  4.     :date => {
  5.       :formats => {
  6.         :default      => "%Y-%m-%d",
  7.         :short        => "%e %b",
  8.         :long         => "%B %e, %Y",
  9.         :long_ordinal => lambda { |date| "%B #{date.day}, %Y" },
  10.         :only_day     => "%e"
  11.       },
  12.       :day_names => %w(日曜日 月曜日 火曜日 水曜日 木曜日 金曜日 土曜日),
  13.       :abbr_day_names => %w(日 月 火 水 木 金 土),
  14.       :month_names => [nil] + %w(123456789101112),
  15.       :abbr_month_names => [nil] + %w(123456789101112),
  16.       :order => [:year, :month, :day]
  17.     },
  18.     :time => {
  19.       :formats => {
  20.         :default      => "%a %b %d %H:%M:%S %Z %Y",
  21.         :time         => "%H:%M",
  22.         :short        => "%d %b %H:%M",
  23.         :long         => "%B %d, %Y %H:%M",
  24.         :long_ordinal => lambda { |time| "%B #{time.day}, %Y %H:%M" },
  25.         :only_second  => "%S"
  26.       },
  27.       :am => '',
  28.       :pm => ''
  29.     },
  30.  
  31.     # date helper distance in words
  32.     :datetime => {
  33.       :distance_in_words => {
  34.         :half_a_minute       => '30分',
  35.         :less_than_x_seconds => '{{count}} 秒以下',
  36.         :x_seconds           => '{{count}} 秒',
  37.         :less_than_x_minutes => '{{count}} 分以下',
  38.         :x_minutes           => '{{count}} 分',
  39.         :about_x_hours       => '約 {{count}} 時間',
  40.         :x_days              => '{{count}} 日',
  41.         :about_x_months      => '約 {{count}} ヶ月',
  42.         :x_months            => '{{count}} ヶ月',
  43.         :about_x_years       => '約 {{count}} 年',
  44.         :over_x_years        => '{{count}} 年以上'
  45.       }
  46.     },
  47.  
  48.     # numbers
  49.     :number => {
  50.       :format => {
  51.         :precision => 3,
  52.         :separator => '.',
  53.         :delimiter => ','
  54.       },
  55.       :currency => {
  56.         :format => {
  57.           :unit => '¥',
  58.           :precision => 2,
  59.           :format => '%u%n'
  60.         }
  61.       }
  62.     },
  63.  
  64.     # Active Record
  65.     :activerecord => {
  66.       :errors => {
  67.         :template => {
  68.           :header => "{{model}}でエラーが発生しました",
  69.           :body => "以下のメッセージを確認してください:",
  70.         },
  71.         :messages => {
  72.           :inclusion => "は、リストに含まれていません",
  73.           :exclusion => "は、有効な値ではありません",
  74.           :invalid => "は、妥当な値ではありません",
  75.           :confirmation => "は、確認できません",
  76.           :accepted  => "は、入力できません",
  77.           :empty => "は、何も入力されていません",
  78.           :blank => "は、空白です",
  79.           :too_long => "は、長すぎます ({{count}}文字以下)",
  80.           :too_short => "は、短すぎます ({{count}}文字以上)",
  81.           :wrong_length => "は、桁数が合っていません({{count}}桁必要です)",
  82.           :taken => "は、有効ではありません",
  83.           :not_a_number => "は、数字ではありません",
  84.           :greater_than => "は、{{count}}文字を超えて入力されています",
  85.           :greater_than_or_equal_to => "は、{{count}}文字以上入力されています",
  86.           :equal_to => "は、{{count}}と同値です",
  87.           :less_than => "は、{{count}}文字未満です",
  88.           :less_than_or_equal_to => "は、{{count}}文字以下で入力されています",
  89.           :odd => "は、端数が入力されています",
  90.           :even => "は、偶数が入力されています"
  91.         }
  92.       },
  93.     },
  94.   }
  95. }


エラーメッセージが日本語になった!
でもnoteとかTitleとかBodyとか中途半端だ。
Modelの属性名もちゃんと日本語化したい。

モデルの属性名を翻訳

config/locales/ja-JP.ymlを以下にように編集して、サーバを再起動する

  1. ja-JP:
  2.   activerecord:
  3.     models:
  4.       note: ノート
  5.     attributes:
  6.       note:
  7.         title: タイトル
  8.         body: 本文


おー、モデルの属性値も日本語化された。
完璧、完璧。

しかし、New Noteとかの文言も日本語化したいと思うのが親心というもの。

モデル以外の文言も翻訳する

config/locales/ja-JP.ymlを以下のように編集

  1. ja-JP:
  2.   activerecord:
  3.     models:
  4.       note: ノート
  5.     attributes:
  6.       note:
  7.         title: タイトル
  8.         body: 本文
  9.   label:
  10.     notes:
  11.       new_note: 新しいノートを作成
  12.       create: 作成する
  13.       back: 前の画面へ


そしてapp/views/notes/new.html.erbを

  1. <h1><%= t('label.notes.new_note') %></h1>
  2.  
  3. <% form_for(@note) do |f| %>
  4.   <%= f.error_messages %>
  5.  
  6.   <p>
  7.     <%= f.label :title, t('activerecord.attributes.note.title') %><br />
  8.     <%= f.text_field :title %>
  9.   </p>
  10.   <p>
  11.     <%= f.label :body, t('activerecord.attributes.note.body') %><br />
  12.     <%= f.text_area :body %>
  13.   </p>
  14.   <p>
  15.     <%= f.submit t('label.notes.create') %>
  16.   </p>
  17. <% end %>
  18.  
  19. <%= link_to t('label.notes.back'), notes_path %>


ちょっと冗長な気がするけど気にしない気にしない
サーバを再起動して確認すると

できたー。
基本はロケールファイルにハッシュで翻訳メッセージを記述していき
tメソッドで呼び出すという感じみたいだ。

gettextほどお手軽ではないけれども、今後スタンダードになっていくのだから今から覚えておいても損はないはずだ。

ファイル一式

今回作成したファイル。

sample.zip

Posted in ruby, ruby on rails at 11月 13th, 2008. Trackback URI: trackback
Tags: , ,

2 Responses to “Rails2.2の新機能i18nを使ってみる”

  1. 2月 23rd, 2009 at 5:40 PM #yuum3のお仕事日記

    [Ruby] Ruby on Rails 2.3 で I18N を使ってみた

    バージョン2.2はスキップしてしまったので、正式なI18Nを使うのは バージョン2.3 が初めてです。 Rails2.2の新機能i18nを使ってみる – func09 が大変参考になりました。 ただし、この記事はバ…

  2. 2月 26th, 2010 at 10:25 PM #Rails 2.3.5 で i18n を使ってメッセージを日本語化する : Serendip - Webデザイン・プログラミング

    [...] リソースファイルの内容はこちらのサイト『Rails2.2の新機能i18nを使ってみる – func09』の翻訳メッセージを参考にした。 [...]

Leave a Reply