诗歌rails 之 i18n
所谓的国际化:就是根据特定的locale信息,提取相应的字符串和其它一些东西(比如时间和货币的格式)等等。
显然,有三个问题需要解决:
1. 如何确定locale。
2. 如何保存这些locale相关的字符串和其它信息。
3. 如何根据locale提取字符串和其它相应的信息。
让我们来看看rails如何处理国际化。(指rails2.2之后)
首先看看第一点,如何确定locale
可以通过几种不同的方法来确定locale。
a. url参数
- http://www.example.com?locale=cn
- 或者
- http://www.example.com/cn
在服务器端可以通过在before_filter中获取locale信息:
- # 通过before_filter
- before_filter :set_locale
- def set_locale
- I18n.locale = extract_locale_from_uri
- end
要注意的是,如果通过此种方法来确定locale,那么所有的url都得附上locale参数。我们可以通过重载以下方法(url_for等方法均依赖于default_url_options方法)
- # app/controllers/application_controller.rb
- def default_url_options(options={})
- logger.debug "default_url_options is passed options:#{options.inspect}\n"
- { :locale => I18n.locale }
- end
或者通过设置routes在所有的url中加上prefix:
- # routes.rb
- map.resources :books, :path_prefix => '/:locale'
b. 域名
- http://www.example.cn
对域名方式,同样在before_filter中获取locale信息。只不过修改一下extract方法:
- def extract_locale_from_subdomain
- parsed_locale = request.subdomains.first (available_locales.include? parsed_locale) ?
- parsed_locale : nil
- end
c. 客户端提供的信息
客户端可以提供一些信息告诉服务端它所接受和期望的语言是什么。可以有以下几种方式来告知:
c.1. Accept-Language
通过在浏览器中设置Accept-Language,服务器端通过获取此http header的信息来确定。
- def extract_locale_from_accept_language_header
- request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first
- end
c.2. ip地址
根据ip地址来分析用户的locale信息。
c.3. profile
注册用户可以把locale信息保存在个人档案中。
接下来让我们看看rails如何解决第二个问题
如何保存locale相关的字符串和其它信息
rails必须知道,本地化的信息被放置何处。在Rails中有几种方法来保存locale信息。
a. yml
- # config/locale/en.yml
- en:
- hello_world: Hello World
- hello_flash: Hello Flash
- # config/locale/pirate.yml
- pirate:
- hello_world: Ahoy World
- hello_flash: Ahoy Flash
b. 本地化view
一般我们的view template文件是这样的:
- app/views/somethings/index.html.erb
当在同个目录下放置一个加上本地化变量的template文件,比如:
- app/views/somethings/index.cn.html.erb
当本地locale是cn时,便会render这个文件。
c. 对本地化文件的管理
把所有本地化信息都放置在一个文件中必然会导致混乱,我们可以按照自己的方式来管理这些本地文件,比如:
- |-defaults
- |---es.rb
- |---en.rb
- |-models
- |---book
- |-----es.rb
- |-----en.rb
- |-views
- |---defaults
- |-----es.rb
- |-----en.rb
- |---books
- |-----es.rb
- |-----en.rb
- |---users
- |-----es.rb
- |-----en.rb
- |---navigation
- |-----es.rb
- |-----en.rb
要注意的是,rails默认不会load层级目录中的文件,所以需要:
- # config/environment.rb config.i18n.load_path += Dir[File.join(RAILS_ROOT, 'config', 'locales', '**', '*.{rb,yml}')]
好了,我们已经知道如何放置本地化信息,最后来看一下rails如何根据locale获取这些信息。其实,这里要讲的就是rails国际化API。
提取信息
rails提供了一下几个API:
- translate # Lookup text translations
- localize # Localize Date and Time objects to local formats
以及它们的alias:
- I18n.t 'store.title'
- I18n.l Time.now
在需要本地化的地方,只需要这样使用:
- # app/views/home/index.html.erb
- <h1><%=t :hello_world %></h1>
- <p><%= flash[:notice] %></p
- <p><%= l Time.now, :format => :short %></p>
如果想跟进一步的了解rails的i18n,可以看一下这篇文章:http://guides.rubyonrails.org/i18n.html
例子:
http://github.com/svenfuchs/rails-i18n/tree/master/rails/locale
http://github.com/rails/rails/blob/master/activerecord/lib/active_record/locale/en.yml