论坛首页 编程语言技术论坛

I18n for Rails

浏览 10940 次
锁定老帖子 主题:I18n for Rails
该帖已经被评为精华帖
作者 正文
   发表时间:2007-02-25  
作为 Web 的 Framework ,国际化 (Internationalization, i18n) 是不可以不考虑的问题。可是 Ruby on Rails 未有如 Java  的 Resource Bundle在语言层次上支援i18n。如果想要 i18n 又不想自行编写程,可用的方案有 Ruby 的 Gettext  或 Rails 的 Globalize。两者都是很强大的plugin,它们甚至支援 data model 层面的i18n。

可是在我的工作中我可不需要这等威力强大的工具,我只想为我简单的软件的输出加入多语言的功能。我发现 th0fu 在 他的 blog mir.aculo.us 中发表了一个非常简单但功能强大的 Localization 方案,它的优点包括:

  • 细小,只用一页程式就为Rails加入l10n支援。
  • 简单,它的做法是extend了Object,为它加入新的方法。使用它作l10n很简单,只需要设定了语言,再把原本的字串 "blah"改为用 _("blah") 或 (在rhtml中) <%=_ "blah" %> 表达就行了。

他的概念很接近我想要的东西,在他的基础上,我加入了以下改动:

  • 使用yml储存资料[*]利用route和filter功入动态切换语言的功能
  

安装方法很简单:
1. 把 i18n.rb 放到 /PROJECT/lib/ 下

# I18n Module 
# License: http://www.apache.org/licenses/LICENSE-2.0.html 
# URL: http://www.reality.hk/articles/2007/02/20/681/ 
# 
# Modified from Localization module at mir.aculo.us 
# http://mir.aculo.us/2005/10/03/ruby-on-rails-i18n-revisited 
 
module I18n 
  mattr_accessor :lang 
 
  @@l10s = { :default => {} } 
  @@lang = :default 
 
  def self._(string_to_localize, *args) 
    translated = 
      @@l10s[@@lang][string_to_localize] || string_to_localize 
    return translated.call(*args).to_s if translated.is_a? Proc 
    translated = 
      translated[args[0]>1 ? 1 : 0] if translated.is_a?(Array) 
    sprintf translated, *args 
  end 
 
  def self.load 
    loaded = [] 
    Dir.glob("#{RAILS_ROOT}/config/lang/*.yml"){ |yml| 
      name = File.basename(yml, ".yml") 
      translate = YAML.load_file(yml) 
      I18n.define(name, translate) 
      loaded << name 
    } 
    return loaded 
  end 
 
  def self.define(lang = :default, dictionary = {}) 
    @@l10s[lang] ||= dictionary 
  end 
 
  def self.lang?(lang) 
    @@l10s.key?(lang) 
  end 
end 
 
class I18nFilter 
  def self.filter(controller) 
    usr_lang = controller.request.path_parameters['lang'] 
    I18n.lang = I18n.lang?(usr_lang) ? usr_lang : :default 
  end 
end 
 
class Object 
  def _(*args); I18n._(*args); end 
end


2. 在 /PROJECT/config/environment.rb 中加入一句:I18n.load ,这让 I18n 读取 yml 翻译档。

Rails::Initializer.run do |config| 
  # Load Localization 
  I18n.load 
end


3. 在 /PROJECT/app/controllers/application.rb 中加入一句:before_filter I18nFilter 。目的是在处理 request 前先查看 request 的 language 再决定 i18n 的输出。

# Filters added to this controller will be run for all controllers in the application. 
# Likewise, all the methods added will be available for all controllers. 
class ApplicationController < ActionController::Base 
  before_filter I18nFilter 
end


4. 在 /PROJECT/config/lang/ 下加入yml翻译档。格式是基本的yaml,key: value,很易明白吧?

Show: 显示
Edit: 修改
Delete: 移除
Previous page: 上一页
Next page: 下一页


5. 在 /PROJECT/config/routes.rb 把原本的default route 更改,目的是在网址中加入语言的选项。你可以自行设定 url 的格式,只要把 lang 放到 path 下就行了。

ActionController::Routing::Routes.draw do |map| 
  map.connect ':lang/:controller/:action/:id' 
end


6. 在 Application 中把所有字串也转为以下格式:

# Call from anywhere (extension to Object class): 
_('blah') 
_('testing %d', 5) 
 
# in .rhtml 
<%=_ 'testing %d', 1 %>


重新启动server后,原本的网址 http://host/PATH 要改为 http://host/LANG/URL。例如输入 http://server/zh-TW/admin 和 http://server/en-US/admin 就可以看见两种语言的网页了 (如果没有设定某个语言,或者某个语言下没有翻译,i18n 会自动输出原本的 key。方便起见通常我都会以英文作 key,那就让系统自动输出英语了。)。
   发表时间:2007-02-25  
谢谢分享,这也是我想要的东西。
0 请登录后投票
   发表时间:2007-06-06  
把这东西改成了 rails 的 plugin,减少了些需要手动的部份,安裝時輸入以下指令就行了。

script/plugin install http://mod-i18n.googlecode.com/svn/trunk/i18n 


详情请看在 Google 的专案网站(http://code.google.com/p/mod-i18n/wiki/InstallationProcedure)
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics