エラーメッセージの国際化(4)

2009/01/24

前回に引き続きエラーメッセージの国際化がテーマです。

今回は「1個の入力エラーがあります」のような、数字を埋め込むタイプのエラーメッセージを英語と日本語で表示する方法について説明します。


asagao アプリケーションの app/views/accounts/_errors.rhtml に次のような記述があります(5行目)。

<div id="errorExplanationHeader"><%= member.errors.length %>個の入力エラーがあります。</div>

これを次のように修正します。

<div id="errorExplanationHeader"><%= t('activerecord.errors.template.header',
  :count => member.errors.length) %></div>

続いて、config/locale/activerecord_ja.yml を次のように修正します。

ja:
  activerecord:
    (省略)
    errors:
      (省略)
      models:
        member:
          taken: が他の方と重なっています。
          attributes:
            password:
              confirmation: が確認用パスワードと一致しません。
            uploaded_image:
              too_large: "のサイズが大き過ぎます(最大64KB)。"
      template:
        header: "{{count}}個の入力エラーがあります。"

そして、config/locale/activerecord_en.yml を次のように修正します。

en:
  activerecord:
    (省略)
    errors:
      (省略)
      models:
        member:
          attributes:
            uploaded_image:
              too_large: "is too large (maximum is 64KB)"
      template:
        header:
          one:    "There is an error"
          other:  "There are {{count}} errors"

_errors.rhtml の中で t メソッドに与えた :count オプションの値が、メッセージの中の {{count}} の部分に埋め込まれます。

『基礎 Ruby on Rails』では利用しませんでしたが、もともと Rails には error_messages_for というヘルパーメソッドがあります。

Rails 2.2 では、このメソッドも国際化されています。

実は、翻訳ファイルの activerecord.errors.template.header というキーワードは、この error_messages_for で使用されるエラーメッセージに対応しています。

なお、英語の場合は、エラーの個数が 1 個であるか 2 個以上であるかによって形が変わるので、header の下に、oneother というサブキーワードを設けて、二つのメッセージを用意する必要があります。

count の個数によってメッセージを変化させる必要がある場合、以下のサブキーワードを指定できます。

  • zero
  • one (単数)
  • two (双数)
  • few (Paucal)
  • many
  • other

詳しくは unicode.org の Language Plural Rules を参照してください。


ところで、今回のテーマとは離れますが、アカウントの編集フォームを表示するとパスワード欄がブラウザによってオートコンプリート(自動補完)されてしまうことに気付きました。

つまり、ログイン時にブラウザにパスワードを記憶させると、編集フォームのパスワード欄にも自動的に値が入ってしまうのです。

これはちょっと都合がよくありません。

app/views/accounts/edit.rhtml の 65 行目は次のようになっています。

      <div><%= form.password_field :password, :size => 30 %></div>

これを次のように修正すると、オートコンプリートが off になります。

      <div><%= form.password_field :password, :size => 30, :autocomplete => 'off' %></div>