背景:
字符数据是最为重要的数据类型,为什么呢 ? 因为程序是为人服务的,那些能直接读懂二进制数据的超人是很少的
。但是如何用二进制数据表示字符呢 ? 这个时候“编码”就诞生了,简单来说,编码就是二进制数据和字符之间建立的映射。ASCII码出现了。但是世界这么大,给你一个字符,你如何知道这是哪种文字的字符属于哪个国家哪种文化呢(火星文除外)? 刚开始出现的ASCII码,只是面向英语的,像欧洲国家的人就没有那么福分去享受这个字符集了,于是就出现了所谓的世界字符集Unicode,有人说Unicode只有65530个字符,其实是不对的。实际上它可以表示无限个字符。

要点:
如果你在Ruby中想使用不同的字符集,那么请记住$KCODE这个全局变量,该变量有常用的五种设置,每种设置都是单个不区分大小写的字母:
1. a: ASCII
2. n : NONE(ASCII)
3. e: EUC
4. s: SJIS
5. u: UTF-8
你可以这么设置,$KCODE = 'u' ,也可以这么设置,$KCODE = 'UTF-8' , 仅仅第一个字符(U)管用。

当使用utf-8的时候require  jcode这个库会很有帮助。

消息目录是指用特定的语言表示的消息集合,是本地化思想中不可分割的一部分。其思想是,将与语言相关的字符串和应用程序的其他部分分离,这样只需要“插入”不同的目录就可获得用不同语言表示的消息和字符串。Ruby里的GetText-Package库是实现这一功能的最佳方式,这是小日本Masao的劳动结晶(Masao虽然是个小日本,但是我挺佩服这个人的,年纪好像是三十多了吧,除了日常工作,还维护gettext这个库,维护两个blog,一个是日文的,一个是英文的,曾经我也效仿这个小日本写英文blog,但是没有坚持下去,真是失败),Rails的多个国际化插件都是基于Gettext库来实现的。GNU有个gettext程序,小日本写的这个是模仿GNU这个gettext写的ruby实现。

 想使用其基本功能,需要require 'gettext'
 想使用更有用的实用程序,需要require 'gettext/utils'

 Ruby1. 8 .6没有包含这个gettext库,需要自己安装  gem install gettext
 关于gettext有三个关键的术语需要解释:
 1.   po - file  :  可移植的对象文件,是人类可读的形式,每个po-file对应一种文化的语言,也叫模板文件。
 2.  mo - file :是可移植的二进制消息目录文件,是根据po-file创建的Ruby库读取的是mo-file,而不是po-file。
 3.  text domain : 文本域,实际上是mo-file的basename,这个是和应用程序所绑定的。

 所以有了文本域,和应用程序绑定以后,我们只需要写一个po-file文件,然后生成mo-file文件,就可以实现本地化了

网上找了个简单的例子:
 require 'gettext'
 class Person
    include GetText

    def initialize(name, age,children_num)
        @name, @age, @children_num = name, age, children_num
         blindtextdomain("myapp")
    end

    def show
         puts  _("information")
         puts  _("Name: %{name}, Age: %{age}")  % {:name => @name, :age => @age}
         puts  n_("%{name}  is an unmarried.", "%{name} has %{num}  boy or girl  firend.", @firend_num)  %  {:name => @name, :num => @firend_num }
    end
 end

 alex = Person.new("Alex",26, 0 )
 alex.show
 mary = Person.new("Mary", 18, 0)
 mary.show

 上面的例子里,
 puts  _("Name: %{name}, Age: %{age}")  % {:name => @name, :age => @age} ,这种写法我估计是gettext里实现的。
 n_方法是除了单复数的。将上面的文件保存为myapp/person.rb, 然后再创建一个myapp/Rakefile文件 , 主要目的是为了更新po-file和创建mo-file
 require 'gettext/untils'

 desc "Update pot/po file"
 task :updatepo do
    GetText.update_pofiles("myapp", ["person.rb"], "myapp 1.0.0")
 end

 desc "Create mo-files"
 task :makemo do
     GetText.create_mofiles
 end

 上面的代码中,update_pofiles将根据person.rb创建初始的myapp/po/myapp.pot, 当它第二次被调用的时候,会对myapp/po/myapp.pot及所有的myapp/po/#{lang} /myapp.po 文件进行更新和合并。此方法的第二个参数是目标文件组成的数组。
   create_mofiles 将创建子目录data/locale/, 并根据po-file生成mo-file。

 这样,当我们执行rake updatepo这个命令之后,将创建目录 myapp/po/myapp.pot.    打开myapp.pot这个文件会看到对应用程序的一些描述信息,是注释掉的,注释行里有这样一行:

  #, fuzzy

 这个表示是还没有被翻译的内容或者是需要校译的内容。
 然后我们就可以复制myapp.pot这个文件为myapp.po,来发给翻译者了。翻译者把翻译好的po文件(这个时候那个fuzzy就应该被移除)发给开发者,然后把这些po文件放到相应的语言目录下,比如中文的放在:
 myapp/po/zh_ch/myapp.po目录下,德文的放在myapp/po/de/myapp.po下。   然后我就执行rake makemo,这样程序会根据这些po文件生成mo文件,生成的mo文件将放在myapp/data/locale目录下。整个目录结构如下:
myapp/
   Rakefile
   person.rb
   po/
       myapp.pot
       zh_cn/myapp.po
       de/myapp.po
       .
       .
   data/
          locale/
                  zh_cn/LC_MESSAGES/myapp.mo
                  de/LC_MESSAGES/myapp.mo
                  .
                  .

然后我们可以测试一下:
首先我们需要设置环境变量,
 export GETTEXT_PATH="data/locale"
 export LANG="zh_CN.UTF-8"
 ruby person.rb
 这样应用程序会根据变量LANG的设置情况输出对应的值。

 以上设置环境变量主要是为了在控制台下测试这个简单程序而已,在本地化应用里将不会使用这个环境变量。