`
andyhu1007
  • 浏览: 199452 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

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

分享到:
评论
1 楼 windix 2009-07-21  
感谢您的总结. 近日使用i18n, 补充一点在官方guides里面也没提到的问题, 关于"复数形式".

Guides的4.3 Pluralization中提到复数可以这样设置和使用:
I18n.backend.store_translations :en, :inbox => {
  :one => '1 message',
  :other => '{{count}} messages'
}

I18n.translate :inbox, :count => 2
# => '2 messages'


其实设置只需要在Locale yml文件里面加上这样一段即可, 效果是一样的:
en: 
  inbox:
    one:  '1 message'
    other:  '{{count}} messages'

相关推荐

Global site tag (gtag.js) - Google Analytics