`
qualenac
  • 浏览: 63606 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类

Rails的国际化和本地化技术[转]

阅读更多

http://rc.org.cn/viewthread-282

skyover 发表于: 2007-7-07 23:11 来源: Ruby Community

问题描述

我们在开发rails或者ruby程序过程中经常会面临这样的问题,就是如何让我们开发出来的程序支持多国语言,而不只是英语或者中文,以及如何让rails的英文提示都变成中文的,甚至其他语言的文字。比如,当我们使用rails的校验机制对用户输入的表单数据进行校验时,我们希望呈现给用户的错误提示全部是中文的而不是中英文混杂的,甚至最好能根据用户浏览器的语言偏好信息来选择页面使用的语言文字。

有很多种方法能够实现这种需求,但是比较完整和比较系统的方法是使用Ruby-Gettext包来实现Rails程序、Ruby程序的国际化和本地化。Ruby-Gettext是Masao Mutoh开发的一个利用GNU gettext库实现的ruby国际化程序库。Ruby-Gettext包的文档在这里,用Ruby-Gettext对Rails进行I18n和L10n的一个示例截屏在这里。其中对中文的支持效果如下:

图-1. 用ruby-gettext进行中文本地化后的rails程序效果,摘自Masao Mutoh的ruby-gettext文档


图1.png


图1

可以看到用ruby-gettext做出来的rails本地化(中文)非常完整,并且下面会看到,让它支持其他语言也是易如反掌。不需要对代码有任何的修改,只需把要翻译的内容交给翻译者,然后把翻译后的文件放入系统中就完成了L10n(本地化)的工作。下面让我们一起来探索如何使用Ruby-Gettext轻松进行国际化和本地化的开发吧!
知识要求

这里假设读者已经掌握了常用的Ruby程序开发技术以及初步的Rails程序开发技术,知道Rails中的数据库迁移(migration)的概念。知道ruby gems 包管理系统的相关知识。知道常用的Mysql数据库使用知识。知道常用的Linux日常命令。

第一个I18n(国际化)的ruby程序hello_i18n !

“等一下,我们的这篇文章不是探索rails国际化和本地化技术的吗,为什么要研究ruby程序的国际化和本地化呢?”,也许你会这样问。这是因为通过对一个很简单的ruby程序的国际化和本地化实现进行探索,可以很好地说明Ruby-Gettext的安装、使用以及工作原理。可以循序渐进地让我们学会如何对rails进行国际化和本地化开发。

下面我们先列出完成一个ruby程序国际化和本地化的操作步骤清单,然后逐一讲解。

   1. 安装ruby-gettext gem包。
   2. 编写hello_i18n.rb Ruby程序。
   3. 抽取代码中需要翻译的内容串,创建POT文件
   4. 创建、翻译PO文件并创建MO文件
   5. 运行本地化后的程序

安装ruby-gettext gem包

运行下面的命令进行安装:(注:$符号是命令提示符,表示这是一条shell命令,不需要输入的)

CODE:

$ gem install gettext如果正常,会得到下面的提示,否则可能是网络或者ruby gem服务器暂时有问题,可以多试几次。因为我的操作系统是Linux,所以我选择2。如果你是在windows下,那么就选择1。

清单-1. 安装gettext gem的提示

CODE:

Bulk updating Gem source index for: [url]http://gems.rubyforge.org[/url]
Select which gem to install for your platform (i686-linux)
1. gettext 1.9.0 (mswin32)
2. gettext 1.9.0 (ruby)
3. gettext 1.8.0 (mswin32)
4. gettext 1.8.0 (ruby)
5. Skip this gem
6. Cancel installation
> 2
Building native extensions. This could take a while...
Successfully installed gettext-1.9.0
这样我们就安装好了Ruby-Gettext gem。可以用“ruby --version”来查看ruby解释器的版本信息,我使用的ruby解释器的版本是“ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-linux]”,如果你的操作系统是windows那么你最好使用ruby one click安装包。可以用“gem -version”来查看gem的版本信息,我使用的gem版本是“0.9.2”。检查一下是否Ruby-Gettext安装是否正确。执行irb然后输入下列语句:

清单-2. 检查Ruby-Gettext gem是否正确安装

CODE:

irb(main):001:0> require 'rubygems'
=> true

irb(main):002:0> require 'gettext'
=> true

irb(main):003:0> GetText
=> GetText
如果你的结果和上面一样,那么恭喜你,你已经正确地安装了Ruby-Gettext gem!如果提示“没有定义GetText这个常量”,那么说明你安装Ruby-Gettext gem有问题,或者是使用了旧版本的gem和ruby。可以根据你的gem和ruby环境下正确使用gem的方法进行调整,只要能正确装载Ruby-Gettext gem并可以找到GetText符号就可以。然后按照你的这个可行的方法修改下面代码中使用Ruby-Gettext gem的方法。

编写hello_i18n.rb文件

用你最喜欢的ruby开发工具或者文本编辑工具创建一个文件“hello_i18n.rb”,它的内容如下:



清单-3. hello_i18n.rb的代码

CODE:

require 'rubygems'
require 'gettext'
include GetText

bindtextdomain("hello_i18n")
print _("Hello I18N World\n")
重点在“print _("Hello World\n")”这个写法上,其中的“_("Hello World\n")”就完成了国际化(支持多种语言),因为当运行时,gettext会根据系统的“地区”设置自动选择合适的语言文字替换此处的字符串。我们检查一下程序是否书写正确,运行下面的命令:


清单-4. 运行没有本地化的 hello_i18n.rb

CODE:

$ ruby hello_i18n.rb
Hello I18N World
如果你也出现上面的提示,那么恭喜你,你的国际化程序写对了!很简单吧!下面我们开始进行本地化工作。

抽取代码中需要翻译的内容串,创建POT文件

什么是POT文件? 它是Portable Object Template的缩写,下面的小节会介绍,这里我们只需要知道它是用来作为翻译原始模板的文件,包含需要被翻译的内容就可以了。执行下面命令:

CODE:

$ rgettext hello_i18n.rb -o hello_i18n.pot文件的内容如下:

清单-5. hello_i18n.pot的内容

CODE:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#

#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2007-05-20 18:17+0800\n"
"PO-Revision-Date: 2007-05-20 18:17+0800\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email]LL@li.org[/email]>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"

#: hello_i18n.rb:7
msgid "Hello I18N World\n"
msgstr ""
翻译PO文件并创建MO文件

“.pot”文件是PO模板文件,顾名思义,就是用来被翻译的原始文件,所以,我们不能在它里面进行修改,而需要把它拷贝为一个PO文件,让翻译人员在PO文件上进行翻译编辑工作。一种语言对应一个PO文件,如果你要进行多种语言的本地化工作,那么就需要拷贝多个PO文件给不同的翻译人员进行翻译。


清单-6. 拷贝.pot文件到.po文件

CODE:

$ cp hello_i18n.pot hello_i18n.po接着,我们用文本编辑器打开 hello_i18n.po 文件进行翻译,需要注意的是,你的编辑器必须支持UTF-8编码方式。因为,PO文件的内容必须都用UTF-8来编码。

清单-7. 翻译后的hello_i18n.po文件

CODE:

#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2007-05-20 19:22+0800\n"
"PO-Revision-Date: 2007-05-20 19:22+0800\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email]LL@li.org[/email]>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"

#: hello_i18n.rb:7
msgid "Hello I18N World\n"
[color=Red]msgstr "你好国际化和本地化的世界\n"[/color]
注意其中的红色字体那一行,原来是空着的,现在翻译为与msgid对应的中文内容。

接着我们需要用这个PO文件生成供程序读取的MO文件,以便gettext能够快速读取。因为我们的代码中函数“bindtextdomain()”没有带上MO查找路径参数,所以,gettext会在默认的路径中查找MO文件,一般会在“/usr/share/locale/#{lang}/LC_MESSAGES/”或者“/usr/local/share/locale/#{lang}/LC_MESSAGES/”中查找,因为/usr/share/locale中放置了很多系统使用的MO文件,为了方便调试和开发,我们选择把我们的MO文件放置在目录“/usr/local/share/locale/zh_CN/LC_MESSAGES/”中。如果该目录不存在,我们可以用下面的命令创建它:


清单-8. 创建MO存放目录

CODE:

$ mkdir -p /usr/local/share/locale/zh_CN/LC_MESSAGES/然后我们用PO文件创建MO文件:

清单-9. 创建MO文件

CODE:

$ rmsgfmt hello_i18n.po -o /usr/local/share/locale/zh_CN/LC_MESSAGES/hello_i18n.mormsgfmt是ruby-gettext提供的一个生成MO文件的程序,也可以使用GNU的msgfmt程序来生成MO文件。

如果你使用的是windows系统,或者想知道具体的MO文件查找目录都有哪些,并且是以什么顺序查找的,那么可以在生成MO文件之前用“-d”选项运行,这时因为Ruby-Gettext找不到任何MO文件,所以会提示错误,并把MO文件查找目录按照先后顺序列出来。如下:

清单-10. 以调试方式运行ruby程序以显示MO查找路径

CODE:

$ ruby -d hello_i18n.rb
Exception `LoadError' at /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27 - no such file to load -- gettext

Bind the domain 'hello_i18n' to 'Object'. Current locale is #<Locale::Object:0xb78fbb20 @variant=nil, @charset="UTF-8", @orig_str="zh_CN.UTF-8", @script=nil, @country="CN", @modifier=nil, @language="zh">
MO file is not found in
[color=Red]/usr/share/locale/zh_CN.UTF-8/LC_MESSAGES/hello_i18n.mo
/usr/share/locale/zh_CN/LC_MESSAGES/hello_i18n.mo
/usr/share/locale/zh/LC_MESSAGES/hello_i18n.mo
/usr/local/share/locale/zh_CN.UTF-8/LC_MESSAGES/hello_i18n.mo
/usr/local/share/locale/zh_CN/LC_MESSAGES/hello_i18n.mo
/usr/local/share/locale/zh/LC_MESSAGES/hello_i18n.mo
/usr/lib/ruby/gems/1.8/gems/gettext-1.9.0/data/locale/zh_CN.UTF-8/LC_MESSAGES/hello_i18n.mo
/usr/lib/ruby/gems/1.8/gems/gettext-1.9.0/data/locale/zh_CN/LC_MESSAGES/hello_i18n.mo
/usr/lib/ruby/gems/1.8/gems/gettext-1.9.0/data/locale/zh/LC_MESSAGES/hello_i18n.mo
/usr/lib/ruby/gems/1.8/gems/gettext-1.9.0/data/locale/zh_CN.UTF-8/hello_i18n.mo
/usr/lib/ruby/gems/1.8/gems/gettext-1.9.0/data/locale/zh_CN/hello_i18n.mo
/usr/lib/ruby/gems/1.8/gems/gettext-1.9.0/data/locale/zh/hello_i18n.mo
/usr/lib/ruby/gems/1.8/gems/gettext-1.9.0/locale/zh_CN.UTF-8/hello_i18n.mo
/usr/lib/ruby/gems/1.8/gems/gettext-1.9.0/locale/zh_CN/hello_i18n.mo
/usr/lib/ruby/gems/1.8/gems/gettext-1.9.0/locale/zh/hello_i18n.mo[/color]
Hello I18N World
上面清单中红色的部分就是gettext查找MO的目录及其顺序,从高到低,先查找前面的目录,如果没有找到,再查找后面的目录。可以看到,最先查找的目录是“/usr/share/locale/zh_CN.UTF-8/LC_MESSAGES/”,因为在我的系统中,“区域(locale)”环境变量$LANG是“zh_CN.UTF-8”。


运行本地化后的程序

现在,ruby程序的国际化和本地化都已经做完了,是时候我们查看最终成果了。再次运行ruby程序:

清单-11. 运行本地化后的程序

CODE:

$ ruby hello_i18n.rb
你好国际化和本地化的世界
如果你也得到上面的结果,那么恭喜你成功国际化并本地化了一个Ruby程序!


关于国际化、本地化技术的常用术语和概念解释
常用术语

区域(locale):对某个国家的文化习惯的一种正式描述,与该国家或语言有关的翻译被称作这种语言或者国家的区域(locale)。
i18n 和 l10n:他们分别是internationalization(国际化) 和localization(本地化)的缩写。国际化是指让同一个程序能支持多个不同的区域(locale),而本地化是指让程序能够支持用户所选择的区域(locale)。粗略地说,对于多语言的系统而言,国际化通常由程序员实现,而本地化通常由翻译员实现。
NLS:Native Language Support,本地语言支持,是指与国际化和本地化相关的所有活动或者产品功能,是指能够让一个程序支持多语言交互能力。
Gettext:是一个GNU软件项目,是很多GNU程序实现多语言支持的基础,它提供了简单、统一的方式来使国际化、本地化工作尽量简单和尽量不影响原有的程序代码。它的主页在这里。

包含翻译信息的文件

在上面我们提到并且使用了POT, PO文件和MO文件,这里我们进一步对这些文件进行一下解释。

“.po”文件中的字母缩写PO代表Portable Object(可移植对象)的意思,为的是与.mo文件区别,这里MO代表的是Machine Object(机器对象)的意思。PO文件适合于人的读写、编辑,因为它是一个纯文本文件,包含原始的用于翻译的字符串和翻译成某种目标语言后的字符串。一个PO文件仅用于一种目标语言。如果一个package(软件包)支持多种语言,那么一种语言就要有一个这样的PO文件与之对应,于是整个包就由这样一组PO文件组成。

以“.pot”结尾的文件是一种用于翻译的基本模板文件,它一般包含在软件的分发包中,以PO文件格式书写。在上面的例子中,我们正是把一个POT文件拷贝成PO文件,然后编辑PO文件的,每一种语言的PO文件都是从POT文件拷贝而来进行翻译的,而不直接修改POT文件。

“.mo”文件是用于机器读取的文件,它以二进制方式存储,只适合机器解读。它是由rmsgfmt (或msgfmt )读取PO文件进行编译后生成的。

最新回复

skyover at 2007-7-08 01:09:08
下面我们正式地来国际化、本地化一个Rails应用程序“MyBlog”。

先列出需要执行的操作步骤,然后在逐一讨论。操作步骤如下:

   1. 创建一个数据库
   2. 生成Rails应用程序框架代码
   3. 配置Rails使用的数据库连接参数
   4. 创建一个model “article”
   5. 编写数据库迁移(migration)代码并执行数据库迁移操作,生成数据库结构
   6. 设置ruby解释器使用的编码方式和声明ruby-gettext相关的包
   7. 创建一个脚手架model和controller
   8. 初始化ruby-gettext包
   9. 国际化model
  10. 创建Rake任务来完成抽取.pot文件,然后翻译.po文件,最后创建.mo文件的操作
  11. 使用浏览器查看本地化后的效果
  12. 国际化模板



虽然看上去步骤挺多,但是只有红色的才是国际化相关的。下面我们逐一进行介绍。

创建一个数据库

创建一个mysql数据库,mysql的版本必须是4.1以上的版本,这样才支持数据库缺省字符集,这里我们要使用utf8字符集编码。

清单-12 创建数据库

CODE:

mysql> create database blog_development default character set utf8;
Query OK, 1 row affected (0.00 sec)
生成Rails应用程序框架代码

确认你的rails版本是1.2.3及以上的,然后用下面的命令创建一个rails应用程序。

清单-13 创建Rails程序框架

CODE:

rails blog配置Rails使用的数据库连接参数

编辑conf/database.xml文件,设置正确的数据库连接属性,如下:

清单-14 数据库连接参数配置

CODE:

development:
adapter: mysql
database: blog_development
username: root
password:
host: localhost
创建一个model “article”

使用下面的命令创建一个model “article”

清单-15 创建一个model “article”

CODE:

$ ./script/generate model article

exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/article.rb
create test/unit/article_test.rb
create test/fixtures/articles.yml
create db/migrate
create db/migrate/001_create_articles.rb
编写数据库迁移(migration)代码并执行数据库迁移操作,生成数据库结构和数据

编辑migrate文件“db/migrate/001_create_articles.rb”,创建相关的表和字段

清单-16 编辑migrate文件

CODE:

class CreateArticles < ActiveRecord::Migration
  def self.up
    create_table :articles do |t|
      t.column :title, :string, :default => ''
      t.column :description, :text
      t.column :lastupdate, :date
    end
  end

  def self.down
    drop_table :articles
  end
end
执行migrate操作,创建数据库表

清单-17 执行migrate操作,创建数据库结构

CODE:

$ rake db:migrate

== CreateArticles: migrating ==================================================
-- create_table(:articles)
-> 0.0032s
== CreateArticles: migrated (0.0034s) =========================================
检查表是否正确创建(可以跳过)

清单-18 检查是否正确创建了数据库表

CODE:

mysql> use blog_development;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> desc articles;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| title | varchar(255) | YES | | | |
| description | text | YES | | NULL | |
| lastupdate | date | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
设置ruby解释器使用的编码方式和声明ruby-gettext相关的包

编辑文件 conf/environment.rb 在第一行加入下面的语句:

清单-19 设置解释器使用的编码方式并引入需要的包

CODE:

$KCODE = 'u'
require 'jcode'
# 在最后一行加入下面的语句:
require 'gettext/rails'
创建一个脚手架model和controller,model是Article,controller是Blog

清单-20 创建model和controller

CODE:

./script/generate scaffold Article Blog初始化ruby-gettext包

编辑app/controllers/application.rb,加上下面的语句:

清单-21 初始化ruby-gettext包

CODE:

class ApplicationController < ActionController::Base
  init_gettext "blog"
end
这里的参数“blog”是textdomain,也就是给一组相关的pot/po/mo文件起的一个共同的组名,和bindtextdomain中的参数textdomain含义一样。

下面是init_gettext()方法的API文档:

CODE:

ActionController::Base.init_gettext(textdomain, options = {})绑定'textdomain'到所有的controllers/views/models上。参数:

CODE:

    * textdomain: 文本域
    * options:
          o :charset - 输出字符集. 缺省是"UTF-8"
          o :content_type - 文档类型. 缺省是"text/html"
          o :locale_path - locale目录的路径. 缺省是RAILS_ROOT 或者插件的根目录。
你也可以为每个controller单独地绑定一个“文本域”,如果这样就要在每个controller中加入下面的代码:

CODE:

class BlogController < ApplicationController   init_gettext "blog"   :   : end接下来,我们就可以像在Ruby程序中使用ruby-gettext提供的方法一样,在rails的model, controller, view, helper中使用它们了。


国际化model

让我们先来国际化model,以便让由model产生的校验错误提示信息都是本地语言。

加入验证代码

清单-22 国际化model

CODE:

class Article < ActiveRecord::Base
  # Simple
  validates_presence_of :title
  validates_length_of :description, :minimum => 10
  # With messages (Use N_() here)
  validates_presence_of :title, :message => N_("%{fn} can't be empty!")
  validates_length_of :description, :minimum => 10, :message => N_("%{fn} is too short (min is %d characters)")
  # Your own validations (Use _() instead of N_()).

  protected
  def validate
    unless title =~ /\A[A-Z]+\z/
      errors.add("title", _("%{fn} is not correct: %{title}") % {:title => title})
    end
  end

end
这里的验证代码与一般的验证代码不同之处在于使用了一些Ruby-Gettext提供的方法,如:N_( ), _( )。

_( ) 是GetText._(msgid)方法,它会把msgid映射成为对应的翻译字符串,并返回该翻译串。比如:_(“to be translated”) # => “将被翻译”

而N_( ) 是getText.N_(msgid)方法,它不进行翻译,只是提供一个位置让GetText知道有这样一个msgid存在,它返回msgid本身。

所以_( ) 方法与N_( )方法的主要区别就在于是否进行翻译并返回翻译后的内容。因为Ruby-Gettext对validates_系列函数的底层实现进行了修改,所以,不需要在调用时进行消息(:message)的翻译,而只需要在此创建一个msgid即可,真正的转换工作Ruby-Gettext包会处理。而对于自己实现的验证方法,如在errors中增加的错误提示信息,如:

CODE:

errors.add("title", _("%{fn} is not correct: %{title}") % {:title => title})就需要立刻进行翻译,得到一个翻译后的字符串供方法调用使用。

另外,在上面的代码中还有“_("%{fn} is not correct: %{title}") % {:title => title}”的用法,在是Ruby-Gettext对String类的扩展,允许在字符串中使用命名参数,例子中的含义是把{:title => title}中的title变量值嵌入%{title}这个位置。其中%{fn}是Ruby-Gettext的一个特殊命名参数,表示字段名,如在这里就是“title”,并且该字段名会被进行正确的翻译,如在本例中会被翻译为“标题”。

还有一些其他用法,比如复数情况的翻译等,请参考Ruby-Gettext的API文档说明。

创建Rake任务来完成抽取.pot文件,然后翻译.po文件,最后创建.mo文件的操作

在我们能看到最后的效果前,还需要进行本地化(翻译)工作。我们需要从代码中抽取出.pot文件,然后翻译为.po文件,最后创建供程序使用的二进制的.mo文件。为了使这个过程更加方便,我们利用rake来进行自动化。

首先添加一个rake任务,这是通过创建文件 lib/tasks/gettext.rake 并写入下面的内容来实现的。

清单-23 rake任务代码

CODE:

desc "Update pot/po files."
task :updatepo do
  require 'gettext/utils'
  GetText.update_pofiles("blog", Dir.glob("{app,lib,bin}/**/*.{rb,rhtml}"), "blog 1.0.0")
end

desc "Create mo-files"
task :makemo do
  require 'gettext/utils'
  GetText.create_mofiles(true, "po", "locale")
end
现在可以用rake来轻松生成 pot 文件了,执行下面命令即可。

清单-24 执行抽取POT文件的rake命令

CODE:

$ rake updatepo
(in /home/yangbo/doc/我的作品/src/blog)
po/blog.pot
. done.
然后我们像在国际化Ruby程序时一样拷贝.pot文件生成po文件,需要把PO文件放置到特定的目录 po/zh_CN 下,其中zh_CN是根据本PO文件的目标语言而设定的,例如,要翻译成日语则为po/jp目录。

清单-25 拷贝生成

CODE:

$ cd po
$ mkdir zh_CN
cp blog.pot zh_CN/blog.po
翻译zh_CN/blog.po文件,注意要使用utf-8编码保存本文件。翻译后的文件内容如下:

清单-26 翻译后的PO文件

CODE:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy

msgid ""
msgstr ""
"Project-Id-Version: blog 1.0.0\n"
"POT-Creation-Date: 2007-05-26 13:12+0800\n"
"PO-Revision-Date: 2007-05-26 13:11+0800\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email]LL@li.org[/email]>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"

#: app/models/article.rb:-
msgid "article"
msgstr "文章"

#: app/models/article.rb:-
msgid "Article|Title"
msgstr "标题"

#: app/models/article.rb:-
msgid "Article|Description"
msgstr "描述"

#: app/models/article.rb:-
msgid "Article|Lastupdate"
msgstr "更新日期"
这样我们就可以用这个PO文件来生成最后需要的MO文件了。生成MO也可以用我们刚才写好的Rake任务,如下:

清单-27 生成MO文件

CODE:

$ rake makemo
(in /home/yangbo/doc/我的作品/src/blog)
po/zh_CN/blog.po -> locale/zh_CN/LC_MESSAGES/blog.mo
使用浏览器查看本地化后的效果

现在我们终于可以看到最后的效果了。下面我们就来利用Firefox浏览器模拟一个简体中文用户访问我们的blog程序。我们需要设置浏览器的语言选项,以中文优先,比如在firefox中可以如下图所示进行设置:


图2.png


图-2 设置Firefox的语言偏好选择

这样在发送的HTTP请求中会有如下的HTTP头字段信息:

CODE:

Accept-Language: zh-cn,en-gb;q=0.7,en;q=0.3于是rails+ruby-gettext系统会根据该信息选择简体中文locale(区域)进行消息的本地化。设置区域的另一种办法是指定rails程序只使用一种本地化语言,那么不论浏览器选择什么语言,rails程序都只返回该种语言的文字,可以这样设置:

清单-28 固定只显示一种语言

CODE:

class ApplicationController < ActionController::Base
  GetText.locale = "zh_CN"
  init_gettext "blog"
end
为了看到最后的效果,我们启动blog程序的WEBrick服务器,打开浏览器,然后访问这个链接地址“http://localhost:3000/blog/new”,故意空着标题然后提交以便可以得到下面的错误提示页面:


图3.png


图-3 本地化后的model校验错误提示页面

可以看到页面上还有部分文字没有被本地化,它们是view模板中的文字。下面我们接着国际化create方法的模板,将上图中的英文字符串被本地化。

编辑app/views/blog/new.rhtml,修改为下面的内容:

清单-29 国际化new方法的模板

CODE:

<h1><%= _("New article") %></h1>
<% form_tag :action => 'create' do %>
<%= render :partial => 'form' %>
<%= submit_tag _("Create") %>
<% end %>
<%= link_to _('Back'), :action => 'list' %>
编辑 app/views/blog/_form.rhtml,改为下列内容:

清单-30 国际化form嵌套模板

CODE:

<%= error_messages_for 'article' %>
<!--[form:article]-->
<p><label for="article_title"><%= _("Title") %></label><br/>
<%= text_field 'article', 'title' %></p>
<p><label for="article_description"><%= _("Description") %></label><br/>
<%= text_area 'article', 'description' %></p>
<p><label for="article_lastupdate"><%= _("Lastupdate") %></label><br/>
<%= date_select 'article', 'lastupdate' %></p>
<!--[eoform:article]-->
然后执行rake任务更性POT模板和PO模板

清单-31 更性POT、PO文件

CODE:

$ rake updatepo
(in /home/yangbo/doc/我的作品/src/blog)
po/blog.pot
. done.
po/zh_CN/blog.po
. done.
你会发现po/zh_CN/blog.po文件被自动进行了新旧内容的合并,这个功能方便了翻译者对本地化内容的维护。使得我们不必从头再把所有已经翻译过的内容再翻译一次。编辑blog.po文件会发现多了下面的内容:

清单-32 PO文件新增加的内容

CODE:

#: app/views/blog/new.rhtml:5
msgid "Create"
msgstr ""

#: app/views/blog/new.rhtml:8
msgid "Back"
msgstr ""

#: app/views/blog/_form.rhtml:7
[color=Red]#, fuzzy
msgid "Description"
msgstr "描述"[/color]
特别注意红色的fuzzy一行,它表示Description在原来的msgid中已经存在,但原来的msgid是带有上下文方式的(也就是形如 msgid "Article|Description" 方式的msgid),需要翻译者确认原来的翻译是否在这里也适用。确认后需要把#, fuzzy一行去掉,否则,该消息ID的翻译内容不会生成到mo文件中去,最后的效果就是没有该消息ID的本地化翻译内容与之对应了。其余部分用之前的方法进行翻译,然后执行rake命令生成MO文件:

清单-33 生成MO文件

CODE:

$ rake makemo
(in /home/yangbo/doc/我的作品/src/blog)
po/zh_CN/blog.po -> locale/zh_CN/LC_MESSAGES/blog.mo
运行blog网页应用程序,执行之前的创建文章操作,故意空着标题栏,得到完全本地化的页面:

图-4 最后完全国际化和本地化后的页面效果


图4.png


图4

小结

本文介绍了如何使用Ruby-Gettext来进行ruby程序和rails程序的国际化与本地化开发。通过两个例子循序渐进地介绍了使用Ruby-Gettext进行ruby、rails程序国际化开发的方法和相关知识。通过阅读本文,读者可以掌握国际化Ruby、Rails程序的技术。为读者进一步了解、使用Ruby-Gettext打下良好的基础。


作者简介

杨波 <bob.yang.dev (at) gmail.com>
早期使用VC++在windows平台下做桌面软件产品开发,之后多年使用java语言进行开发,主要从事电信增值业务开发,从2006年开始接触和使用ruby和ruby on rails进行一些开发。目前是结信网络有限公司的技术经理,从事特定领域(彩铃)搜索引擎产品和自然语言处理方面的研发工作。也是一个Ruby, Rails的爱好者。

本文章版权归杨波所有,欢迎转载,但必须注明作者。如果需要用于商业目的,请与作者联系

Rails国际化和本地化技术.pdf
(2007-07-08 01:11:33, Size: 378 KB, Downloads: 11)

示例代码hello_i18n.zip
(2007-07-08 01:11:33, Size: 1.61 KB, Downloads: 7)

示例代码——myblog.zip
(2007-07-08 01:11:33, Size: 77 KB, Downloads: 4)

分享到:
评论

相关推荐

    Wrox.Professional.Ruby.on.Rails.Feb.2008

    书中深入探讨了诸如用户管理、安全性、时区处理、国际化、团队协作、自动化构建任务、部署生产环境服务器、网站安全加固以及如何利用Rails社区中的优秀资源等内容。 #### 知识点详解 **第1章:构建资源** - **...

    主流PHP框架比较.pdf

    Symfony 1.0.13版本是早期的经典版本,该框架支持PHP 5.3及以上版本,并且具有丰富的国际化和本地化工具。Symfony的官方文档详尽地解释了如何通过YAML配置文件进行项目设置,以及如何使用symfony的自动加载机制来...

    The definitive guide to grails_2 源代码

    10. **国际化与本地化**:源码可能会涉及i18n(国际化)和l10n(本地化)的配置和实现,帮助理解如何在Grails应用中支持多种语言。 通过深入研究《The Definitive Guide to Grails 2》的源代码,开发者不仅可以掌握...

    rail on ruby

    - 可以轻松地为不同语言提供本地化版本。 - **生产环境部署**: - 常见的部署方式包括 Heroku、AWS 和 DigitalOcean 等云平台。 - 需要配置环境变量、数据库连接等。 #### 十、常用 Gem - **Gem**: Rails 项目中...

    (源码)博客引擎项目.rar

    12. **国际化与本地化**:支持多语言,使用i18n库来实现。 13. **性能优化**:缓存策略、CDN(内容分发网络)、代码压缩等手段提高网站加载速度和用户体验。 14. **部署与运维**:Docker容器化、自动化部署脚本、...

    yii中blog完成后的例子

    9. **国际化和本地化**:Yii支持多语言,博客系统可以轻松添加不同语言版本,满足全球化需求。 10. **扩展与插件**:Yii拥有丰富的社区和第三方扩展,可以快速集成到项目中,如SEO优化工具、社交分享插件等。 通过...

    redmine-2.5.1

    4. **国际化与本地化**:增加了对更多语言的支持,满足全球用户的使用需求。 5. **Bug修复**:对之前版本存在的问题进行了修复,提高了软件的稳定性和可靠性。 从文件名称列表"redmine-2.5.1"来看,这是Redmine的...

    2021-2022年收藏的精品资料软件工程师10个jQuery的语言翻译插件推荐.docx

    8. **Lingua Localization Plugin**:专注于web应用的本地化,通过处理含语言键值对的文本文件,部署和使用简便,还支持一定程度的自动翻译。 9. **SpecialEdit**:主要用于文本输入框,添加特殊字符输入功能,尤其...

    jamendo源码

    - **国际化与本地化**:了解如何实现多语言支持,使应用适应不同地区的用户。 通过深入研究"jamendo源码",开发者不仅可以提升自身的编程技能,还能了解一个完整的音乐服务平台是如何运作的,这将对从事相关领域...

    ulearning-asia:ulearning-asia l10n

    4. **国际化和本地化工具**:项目可能使用i18next、gettext或Crowdin等工具来管理翻译工作,确保平台能适应多种语言。 5. **版本控制**:使用Git进行代码版本管理,GitHub或GitLab可能是托管这些代码的地方。 6. *...

    quologia:共享报价的Web服务

    7. 日语支持:服务的本地化,包括日语的界面显示、错误消息和帮助文档,都需要进行细致的本地化工作。 为了深入了解Quologia的实现细节,我们可以查看压缩包中的"quologia-master"目录。这个目录很可能是项目的源...

    globaltravel:环球旅行家

    11. **国际化与本地化**:为了满足全球用户的需求,项目可能支持多语言环境,使用i18n(国际化)库来处理不同地区的语言设置。 12. **云服务**:项目可能部署在AWS、Azure或Google Cloud等云平台上,利用云服务的...

    gym-app2

    在IT行业中,`gym-app2`看起来像是一个与健身相关的应用程序项目,可能是用...实际项目中可能还涵盖了更多其他技术,如错误跟踪、性能优化、国际化和本地化等。要深入了解`gym-app2`,你需要直接查看源代码和相关文档。

    PlantsMeEnglish_PersianAdmin

    综上所述,"PlantsMeEnglish_PersianAdmin"项目涉及的技术和知识面广泛,涵盖了前端和后端开发、数据库设计、多语言处理、版本控制、内容管理等多个方面。对于开发者而言,这是一个锻炼和提升全面技能的好机会。

    商城购物MORNING

    1. **Web开发框架**:为了构建这样的商城,开发者可能使用了像Spring Boot、Django或Ruby on Rails这样的Web开发框架,它们能够简化开发流程,提高代码的可维护性和扩展性。 2. **前端技术**:HTML5、CSS3和...

    shogi-extend:将棋关连の便利ツール集

    综上所述,shogi-extend是一个综合性的将棋工具集,利用了Rails、Vue.js、Bulma等现代技术,为将棋爱好者和开发者提供了便捷的分析、转换和互动功能。无论是从开发角度还是用户使用角度,该项目都展现了强大的功能和...

    currency-converter

    9. **国际化(i18n)**:为了服务全球用户,货币转换器可能需要支持多语言,这就需要了解如何实现国际化和本地化。 10. **部署与持续集成**:项目可能需要部署到云平台,如AWS、Google Cloud或Heroku,并通过Git...

    livro-receitas:Livro de receitas

    8. 国际化与本地化:由于提及了国际菜肴,可能需要支持多种语言,因此会涉及到多语言处理和本地化的技术。 9. 社区参与:开源项目通常鼓励社区成员参与,可能有评论、评分、提交修改等功能,涉及社交网络集成和用户...

    BemoWiki:维基百科

    8. **国际化与本地化**:类似维基百科,BemoWiki可能支持多语言,这意味着需要处理语言切换、翻译和本地化问题。 9. **SEO优化**:为了提高搜索引擎可见性,BemoWiki可能考虑了搜索引擎优化(SEO)策略,如元标签、...

    lynda:只是一个简单的cms

    9. **国际化和本地化**:对于多语言支持,可能会使用I18n gem。 通过这个简单的CMS,开发者可以快速搭建一个用于发布和管理在线教育内容的平台,同时保持代码的简洁性和可维护性。对于学习Ruby on Rails的初学者来...

Global site tag (gtag.js) - Google Analytics