icon 《基础 Ruby on Rails》的示例程序asagao与Rails2.2相适应

ActiveRecord 模型的字段名的国际化

上一章中,在示例应用程序 asagao 中添加了区域切换的功能。

这一章,将着手进行 ActiveRecord 相关的国际化。

使表示某个对象的内容和编辑表单时的字段名能够根据不同的区域进行转换。

在《基础 Ruby on Rails》中,已将常量 REAL_ATTRIBUTE_NAMES 和类方法 real_attribute_name 在每一个模型定义。

例如,在 member.rb 中有如下描述。

  # 属性对应的汉字名
  REAL_ATTRIBUTE_NAMES = {
    :member_number => '球衣号码',
    :player => '选手注册',
    :family_name => '姓',
    :given_name => '名',
    :furigana => '注音假名',
    :email => 'email',
    :phone => '电话号码',
    :birthday => '出生年月',
    :sex => '性別',
    :remarks => '备注',
    :login_name => '用户名',
    :password => '密码修改',
    :administrator => '网站管理者',
    :uploaded_image => '图像'
  }
  
  def self.real_attribute_name(key)
    REAL_ATTRIBUTE_NAMES[key.to_sym]
  end

而且,在模板中有如下语句。

<%= Member.real_attribute_name(:phone) %>

从Rails2.2开始,ActiveRecord::Base的类方法 human_attribute_name 可以内部利用 I18n 模块。

决定用新方法进行改写。

那么,开始吧。


首先,为了确定影响范围,将上述代码从 member.rb 删除,执行测试。

单元测试中没有发生错误。这也未必是好事。这意味着 real_attribute_name 方法的测试没被写入。需要检查。

功能测试中,9个测试失败了。

> rake test:functionals
(省略)
95 tests, 320 assertions, 9 failures, 0 errors

accountsmembersadmin/members 控制台中失败了。和预料一样。

如果用 human_attribute_name 全部置换 real_attribute_name 方法的话,测试应该通过的吧。

用喜欢的编辑器的“统一置换”功能,将 app/views/accountsapp/views/membersapp/views/admin/members 目录下的全部文件中的 real_attribute_name 换成human_attribute_name

再次执行功能测试。

> rake test:functionals
(省略)
95 tests, 320 assertions, 9 failures, 0 errors

啊!不行。出现了这样的错误。

undefined method `humanize' for :member_number:Symbol

虽然 real_attribute_name 方法获取了符号,但是在 human_attribute_name 方法的情况下有必要使用字符串指定字段名。

这表示有必要将 human_attribute_name(:foo) 置换为 human_attribute_name('foo')

虽然也有做如此复杂的置换的编辑器,但是还是让我们来创建一个任何人都能用的小的 Ruby 脚本。

创建一个下面这样的脚本,命名为 humanize.rb 并存在 scrpts 目录下。

dir = ARGV[0]

Dir.glob("app/views/#{dir}/**/*.rhtml").each do |file|
  code = File.open(file).read
  code.gsub!(/real_attribute_name/, 'human_attribute_name')
  code.gsub!(/human_attribute_name\(:(\w+)\)/, 'human_attribute_name("\1")')
  File.open(file, 'w').write(code)
end

执行置换。

> ruby script/humanize.rb accounts
> ruby script/humanize.rb members
> ruby script/humanize.rb admin/members

再次执行功能测试。

> rake test:functionals
(省略)
95 tests, 338 assertions, 3 failures, 0 errors

又出现错误了。

原因是app/views/admin/members/_errors.rhtml

      <strong><%= h(Member.human_attribute_name(attr.to_sym)) %></strong> <%= h(msg) %>

将此做如下修改(去掉.to_sym )。

      <strong><%= h(Member.human_attribute_name(attr)) %></strong> <%= h(msg) %>

再次执行功能测试。

> rake test:functionals
(省略)
95 tests, 341 assertions, 0 failures, 0 errors

OK 了。

> rake test:integration
(省略)

2 tests, 67 assertions, 0 failures, 0 errors

综合测试也通过了。


接下来,生成翻译文件。

config/locales 目录下生成 activerecord_en.ymlactiverecord_ja.yml

activerecord_en.yml

en:
  activerecord:
    attributes:
      member:
        member_number: Member Number
        player: Player
        family_name: Family Name
        given_name: Given Name
        furigana: Furigana
        email: E-mail address
        phone: Phone Number
        birthday: Birthday
        sex: Sex
        remarks: Remarks
        login_name: Login Name
        password: Change Password
        administrator: Administrator
        uploaded_image: Uploaded Image

activerecord_ja.yml

ja:
  activerecord:
    attributes:
      member:
        member_number: 球衣号码
        player: 选手注册
        family_name: 姓
        given_name: 名
        furigana: 注音假名
        email: email
        phone: 电话号码
        birthday: 出生年月
        sex: 性別
        remarks: 备注
        login_name: 用户名
        password: 密码
        administrator: 网站管理者
        uploaded_image: 图像'

运行服务器,以会员身份登陆。

试着更改自己的帐户,使用会员名册和管理页面的会员管理功能。

然后,切换语言,确认字段名表示正确。

追加新的翻译文件时,因为即使在 develope 环境中也有必要重新启动服务器,所以注意一下。

如果仅是修改翻译文件,则不用重启。

asagao アカント英語表示

asagao アカウント日本語表示

和前面叙述的一样,Rails 2.2 的 human_attribute_name 内部利用了 I18n 模型。

如果写成 Member.human_attribute_name('phone') 的话,便和写成 t('activecord.attributes.member.phone') 一样了。

今天就到这儿吧。

(2009/01/08)