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

Gibberish 本地化插件学习

浏览 7938 次
该帖已经被评为良好帖
作者 正文
   发表时间:2007-07-28  
Gibberish是基于rails框架下的一个语言本地化插件, beast项目使用它进行语言本地化。

Gibberish代码不多,也很容易理解,但是很好地实现了语言本地化的功能,读了以后感觉有些收获就写了这篇文档。

一、安装与配置

在rails项目下, 执行
ruby script/plugin install svn://errtheblog.com/svn/plugins/gibberish


在rails项目下,建立 lang 目录,并创建相应语言文件,例如:

en.yml 为英语文件,在其中输入:
login: Login

zh.yml 为中文文件,在其中输入:
login: 登录

这样即可,如果有新的需要本地化字符串,也按同样格式写入两个文件即可。


二、使用方法

通过运行  ruby script/console , 查看一下Gibberish的使用方法。
引用

#初始化加载
>> Gibberish.load_languages!
=> [:zh, :en]

#显示 login
>>  "login"[:login]
=> "Login"

#更改语言为zh

>>  Gibberish.current_language = :zh
=> :zh

>>  "login"[:login]
=> "登录"


稍微复杂的例子是可以写成如下格式

引用
en.yml:
welcome: "Welcome {name}!"

zh:yml:
welcome: "{name},欢迎来访! "

执行:
"welcome"[:welcome,"Mike"]


在不同语言设置时,会显示:

引用
Welcome Mike!

Mike,欢迎来访!


   发表时间:2007-07-28  
三、源码学习

1、初始化加载

    
def load_languages!
   language_files.each do |file| 
      key = File.basename(file, '.*').to_sym
      @@languages[key] = YAML.load_file(file).symbolize_keys
    end
    languages
end


简单地load 相应语言文件yml至 @@languages[key] 中。

2 翻译字符串:

首先, 执行:
String.send :include, Gibberish::StringExt

当Gibberish::StringExt被别的类include时会调用到函数:

	    
def self.included(base)
  base.class_eval do
    alias :brackets :[]
    alias_method_chain :brackets, :translation
    alias :[] :brackets
  end
end


其中:alias_method_chain 大概实现如下:

	
def alias_method_chain(target, feature)
  alias_method "#{target}without#{feature}", target
  alias_method target, "#{target}with#{feature}"
end


所以,再执行String#[]时,会调用到函数 brackets_with_translation

    
def brackets_with_translation(*args)
      args = [underscore.tr(' ', '_').to_sym] if args.empty?
      return brackets_without_translation(*args) unless args.first.is_a? Symbol
      Gibberish.translate(self, args.shift, *args)
    end


当[]中第一个参数不是一个Symbol 还会执行以前的[],否则就执行Gibberish.translate
0 请登录后投票
   发表时间:2007-07-28  
四、使用细节

  已经读过源码对一些使用细节有了更清楚的了解:

  1、可以通过Gibberish::Localize#add_reserved_key添加保留字,如:
引用
>>Gibberish.add_reserved_key(:aaa, :bbb)
>> "bbb"[:bbb]
=> nil


  2、对于“string”[:string] 如果未找到定义的,会返回"string"

  3、“string”[] 相当于 “string”[:string]

  4、 类似welcome: "Welcome {name}!" 这种功能是通过下面代码实现的

	string.gsub(/\{\w+\}/) { args.shift }


所以,它只是把大括号里面的内容,按[]中的参数顺序替换而已。

比如,语言文件定义如下:

引用
hello: hi,{name}! how are you, {name}? are you fine, {name}?


在调用时,应该是
引用
“hello”[:hello, "Mike", "Mike", "Mike"]

而不是
引用
“hello”[:hello, "Mike"]


另外,感觉每次更换语言,还需要set current_language 不太好。
因为,有时不同的用户会选用不同的语言,他们如果同时使用,就比较麻烦。
类似这样的调用似乎更好

引用
"welcome"[:zh, "Mike"]


当然,实现上述功能也非常容易。

五、回顾

ruby的Mixin功能强大,可以很容易在一个Class中,加入另一个module的功能,简单这样即可:
class ClassA
	include ModuleA
end


而ruby还有永不关闭的类的说法,我们可以在任何时候修改以往的类库来实现想要的功能。
在这时通常会需要重载以往已经实现的函数,而在Gibberish中就重载了String#[].

在这种情况下通常都有很固定的模式:

  1、def self.included(base) 该函数会在module被别的类Mixin时候执行。

  2、通过 base.class_eval 执行动态代码

  3、使用  alias_method_chain :brackets, :translation

将原有函数命名为 brackets_without_translation

定义新函数 brackets_with_translation完成重载。
0 请登录后投票
论坛首页 编程语言技术版

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