乐者为王

Do one thing, and do it well.

用Rails 2.3打造简单记账应用(10)

从2.2版本起Rails开始内置支持i18n,因此以后实现国际化/本地化就可以不再需要各种各样的插件了。

Rails默认的Locale文件夹是config/locales,假设你要支持中文和英文,那么你需要在这个文件夹下放置zh.yml和en.yml两个文件。

相应的入门教程网上有不少,我也就不多讲了。这里主要说一下如何在记账应用中实现可以让用户指定语言的i18n实现,即当用户选择English,那么界面就切换成英文界面,并且以后打开的页面也是以英文出现,反之亦如此。

首先在header区添加以下代码:

1
2
<%= link_to 'Chinese', :locale => 'zh' %>
<%= link_to 'English', :locale => 'en' %>

点击其中某个链接后,浏览器就会传递对应的参数zh或en到后台。

然后在app/controllers/application_controller.rb中添加以下代码:

1
2
3
4
5
6
before_filter :set_locale

protected
  def set_locale
    I18n.locale = params[:locale]
  end

不过这里有个问题就是url中必须得带着参数,不然的话用户的选择就会失效。要想使选择达到持续的效果,可以考虑把这些信息保存在session中,改进后的代码如下:

1
2
3
4
def set_locale
  I18n.locale = params[:locale] || session[:locale]
  session[:locale] = I18n.locale
end

现在这样就基本上差不多了。剩下的就是处理第一次访问时的语言,这个可以从request的ACCEPT_LANGUAGE参数中获取。最终实现的代码:

1
2
3
4
5
def set_locale
  accept_lang = request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first
  I18n.locale = params[:locale] || session[:locale] || accept_lang || 'zh'
  session[:locale] = I18n.locale
end

不过当用户选择中文后,在新建记录时会报以下错误:

1
2
3
4
5
6
7
8
can't convert Symbol into String

Extracted source (around line #8):

    6:   <p>
    7:     <%= t(:effective_date) %><br />
    8:     <%= f.date_select :effective_date %>
    9:   </p>

查找资料后发现可以通过在date_select中加入order来解决,不过日期下拉列表中的月份还有问题,出现的是一些随机数,不是正常月份。这个也可以通过添加month_names参数解决。

1
2
<%= t(:effective_date) %><br />
<%= f.date_select :effective_date, :order => [:year, :month, :day] %>

更好的办法是把它们放到对应的Locale文件里:

1
2
3
4
5
# en.yml
en:
  date:
    month_names: [~, January, February, ..., November, December]
    order: [:year, :month, :day]
1
2
3
4
5
# zh.yml
zh:
  date:
    month_names: [~, 一月, 二月, ..., 十一月, 十二月]
    order: [:year, :month, :day]

代码下载:https://github.com/dohkoos/qianbao

Comments