ruby way之国际化之一

这边有几个概念先看一下:


[quote]为了将软件多语言化,首先进行植入能够使用各种语言的设计和方法等的国际化操作(internationalization 118N)。然后针对各种语言,进行能够使用该语言的地区化(localization、L10N)的操作。进行了多种语言的地区化,用户能够切换成自己想使用的语言时的状态称为多语言化(multilingualization、M17N)。[/quote]


这几个概念的简写版,可以通过下面的函数就行简化:


[code]def shorten(str)

(str[0..0] + str[1..-2].length.to_s + str[-1..-1]).upcase

end

puts shorten("internationalization") # I18N

puts shorten("multilingualization") # M17N

puts shorten("localization") # L10N[/code]


其中I18N和M17N基本是 同义的。


1 介绍一下asc和unicode.


ascII和unicode的概念和编码,网上的介绍很多,不理解的可以google一下,我这边简要的介绍一下。


ascII全称是the American Standard Code for Information Interchange,它使用7位二进制表示一个字符的字符集。因此他可以表示2的7次方个字符,也就是128个,不同的字符的表示从0到127.这种表示足够表示绝大部分的美国英语。如果你从一个流中读一个在0到127字节值,然后将它转成char,结果将会是扩展asc码.


接下来是Latin-1字符集


ISO 8859-1, Latin-1是一个8位的二进制表示一个字符的字符集,因此他能表示的值是0到256。并且它是ascII的超集,他的前128个字符是和ascII编码是一样的,它和ascII的区别是在128-256之间的字符,。ascII没有提供这部分的字符,而Latin-1扩展了这部分,用以表示一些非英语的字符,比如拉丁文.如果你从一个流读入一个无符的字节,然后转换它为char,那么它的结果将是Latin-1 的字符.


unicode字符集


Latin-1对于大部西欧的语言来说是足够了,可是像中文,日语之类的语言对于它来说,他所能表示的字符数量就太少了。因此就随之诞生了unicode字符集,unicode能够表示这个世界上大部分的存在的,或者不存在的语言.


unicode字符集的前256个字符是和Latin-1一样的。


unicode只是一个字符集,他并不是字符编码。举个例子,比如unicode它指出了字符A必须表示成65,可是他并没有指出65是用一个字节,两个字节甚至更多的字节来表示,而且它也没有指出这些字节的表示顺序是大端的表示,还是小端的表示.这边有几个unicode到字节的标准编码,最常用的UTF-8, UTF-16, and UTF-32.


UTF-32 它简单的将一个字符编码为一个4字节的int.


UTF-16 大部分时候将一个字符编码为一个2字节的无符short.当对一些的中文,数学符号,等等一些字符进行编码的时候它会将字符编码为4字节(也就是2个2字节的字符).


UTF-8是一个高效的编码使用1个字节来表示所有的ascII字符.2个字节来表示一些其他的字母表,3到4个字节来表示其他的语言,比如中文之类的.


下面来看几个例子:


[quote]"Matz" # 用utf-16来编码的话就是 U+004d U+0061 U+0074 U+007a[/quote]


存储这个字符的话,就是一个字节序列:

[quote]00 4d 00 61 00 74 00 7a[/quote]


我们可以看到 每一个字符的编码都有 00,这个无效的字符,虽然这个例子有点特殊,可是我们还是会遇到这种情况,这种情况下,UTF-16的编码就会比较浪费存储空间。


如果我们使用UTF-8来编码的话,就是下面这种字节序列:


[quote]4d 61 74 7a[/quote]


自己看这个编码,它去掉了所有无效的0,并且这个编码是和ASCII码的编码是一样的,刚好和我们上面说的一样.


2 jcode库与$KCODE


如果要在ruby中使用不同的字符集,你必须要注意这个变量$KCODE,它定义了很多核心方法的操作string的行为。K是Japanese nonalphabetic 的简写.这个变量有5个设置。分别是:

[quote]a ASCII

n NONE (ASCII)

e EUC

s SJIS

u UTF-8[/quote]


当然你也可以使用你所想要的字符集的全写,比如$KCODE = "UTF-8".如果没有指定KCODE变量的话,ruby默认是ASCII编码.
[code]puts $KCODE
$KCODE="n"

eacute=""
eacute<<0303<<0251
sword=eacute+"p"+eacute+"e"
p eacute
p sword
$KCODE="u"
puts eacute
p sword[/code]

正则表达式也可以变得很很聪明在utf-8模式下:

[code]$KCODE="n"

letters=sword.scan(/(.)/)

puts letters.size #6当在默认的ascII编码下sword是由6个字符组成的.

$KCODE="u"

letters=sword.scan(/(.)/)

puts letters.size #4

puts "中国".size #6[/code]
从这个例子我们可以看到,size方法的返回值实际上是这个字符串在某个固定的字符集下被编码为几个字节,从而返回它.

jcode库还提供了一些有用的方法,比如jlength和each_char.

3 重新谈一下字符串和正则表达式的操作。

在utf-8的模式下,很多string的操作我们都可以使用:

[code]
test1="人民共和国"
puts test+test1
puts test1.include?("人民")[/code]

可是,比如一个字符"中国"我们对他求他的长度,这时,我们会得到6,可是其实他看起来只有2个字符,如果我们想到得到2的话,我们就要用到jcode库了:

[code]$KCODE = "u"
require 'jcode'
sword = "中国"
puts sword.jlength #2
puts sword.length #6[/code]

这边要注意的是,jcode库一定要在utf-8的编码下,才能正常工作.

如果对特殊字符比如汉字使用upcase之类的方法,将不会发生任何变化.这个是ruby所作的限制

[code]$KCODE = "u"
require 'jcode'
sword = "中国"
puts sword.count("国") #3
puts sword.jcount("国") #1[/code]

这里还有一个方法,叫做mbchar?的,他检测一个字符串是否是多字节的.

[code]$KCODE = "u"
sword.mbchar? # 0
"foo".mbchar? # nil[/code]

jcode库还重新定义了chop, delete, squeeze, succ, tr, 和tr_s.这些方法.这些方法都是为多字节的字符串所定义的.

我们还可以使用each_char来打印出所有的多字节字符:

[code]puts sword.each_char {|x| puts x } # 中国人[/code]


unpack方法,有选项来帮助我们操作unicode字符串,如果他的参数为U*的话,则将会解码当前的字符串,使用utf-8编码。也就是说他会返回一个整数数组,而对应的还有一个pack方法,他则是编码的:

[code]
puts array=sword.unpack("U*")
puts array.pack("U*")[/code]

正则表达式也可以士多字节的.特别是当你使用Oniguruma 时,例如/./将会匹配单个多字节的字符.

就算没有Oniguruma ,正则表达式也可以聪明的理解一个字符是不是一个多字节的词.

[code]$KCODE = "u"
puts sword =~ /\w/ # 0
puts sword =~ /\W/ # nil[/code]

4 检测字符的编码

经常多字节和单字节之间的编码区别很大,可是如果只是单字节呢,比如单字节的utf-8和ascII的编码就很象了,我们该如何判断呢:

[code]class String
def utf8?
unpack('U*') rescue return false
true
end
end

puts sword.utf8?
[/code]

我们还可以检测纯粹的ascII编码,通过查看他的每一个字节是不是都小于127

[code]class String
def ascii?
self.split(/./).all? {|ch| ch < 128 }
end
end[/code]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值