关于unicode:ruby 1.9:如何正确地对多字节字符串进行大写和小写转换?

Ruby 1.9: how can I properly upcase & downcase multibyte strings?

所以Matz决定在Ruby1.9.1中将upcasedowncase限制在/[A-Z]/i之内。

ActiveSupport::Multibyte在Ruby1.8.x中通过String#mb_chars长期以来都有很好的I18N案例转换。

但是,当在Ruby1.9.1下尝试时,它似乎不起作用。下面是我编写的一个简单的测试脚本,以及我得到的输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ cat test.rb
# encoding: UTF-8

puts("@ #{RUBY_VERSION}" + (__ENCODING__ rescue $KCODE).to_s)
sd, su ="I?t?rnati?nàliz?ti?n","I?T?RN?TI?NàLIZ?TI?N"
def ps(u, d, k); puts"%-30s:  %24s / %-24s" % [k, u, d] end
ps sd.upcase, su.downcase,"Plain ruby"

require 'rubygems'; require 'active_support'
ps sd.upcase, su.downcase,"With active_support"
ps sd.mb_chars.upcase.to_s, su.mb_chars.downcase.to_s,"With active_support mb_chars"

$ ruby -KU test.rb
@ 1.8.7 UTF8
Plain ruby                    :  I?T?RNaTI?NàLIZ?TI?N / i?t?rn?ti?nàliz?ti?n
With active_support           :  I?T?RNaTI?NàLIZ?TI?N / i?t?rn?ti?nàliz?ti?n
With active_support mb_chars  :  I?T?RN?TI?NàLIZ?TI?N / i?t?rnati?nàliz?ti?n

$ ruby1.9 test.rb
@ 1.9.1 UTF-8
Plain ruby                    :      I?T?RNaTI?NàLIZ?TI?N / i?t?rn?ti?nàliz?ti?n
With active_support           :      I?T?RNaTI?NàLIZ?TI?N / i?t?rn?ti?nàliz?ti?n
With active_support mb_chars  :      I?T?RNaTI?NàLIZ?TI?N / i?t?rn?ti?nàliz?ti?n

那么,如何用Ruby1.9.1实现国际化的upcasedowncase

更新

我还要补充一点,我还使用了当前github的master2-3-*3-0-unstable轨道分支的activesupport进行了测试。同样的结果。


对于来自谷歌的任何人,由ruby upcase utf8提供:

1
2
>"your problem chars here ????ü I?t?rnati?nàliz?ti?n".mb_chars.upcase.to_s
=>"YOUR PROBLEM CHARS HERE ???Iü I?T?RN?TI?NàLIZ?TI?N"

解决方案是使用EDOCX1[1]


案例转换依赖于区域设置,并不总是往返的,这就是Ruby1.9不覆盖它的原因(请参阅这里和这里)

unicode-utilgem应该满足您的需求。


案例转换很复杂,而且依赖于区域设置。幸运的是,Martin D_rst在Ruby2.4中添加了完整的Unicode大小写映射:

1
2
3
4
5
6
7
8
9
puts RUBY_DESCRIPTION

sd, su ="I?t?rnati?nàliz?ti?n","I?T?RN?TI?NàLIZ?TI?N"
def ps(u, d, k); puts"%-30s:  %24s / %-24s" % [k, u, d] end
ps sd.upcase,              su.downcase,             "Ruby 2.4 (default)"
ps sd.upcase(:ascii),      su.downcase(:ascii),     "Ruby 2.4 (ascii)"
ps sd.upcase(:turkic),     su.downcase(:turkic),    "Ruby 2.4 (turkic)"
ps sd.upcase(:lithuanian), su.downcase(:lithuanian),"Ruby 2.4 (lithuanian)"
ps"-",                    su.downcase(:fold),      "Ruby 2.4 (fold)"

输出:

1
2
3
4
5
6
ruby 2.4.0dev (2016-06-24 trunk 55499) [x86_64-linux]
Ruby 2.4 (default)            :      I?T?RN?TI?NàLIZ?TI?N / i?t?rnati?nàliz?ti?n
Ruby 2.4 (ascii)              :      I?T?RNaTI?NàLIZ?TI?N / i?t?rn?ti?nàliz?ti?n
Ruby 2.4 (turkic)             :      I?T?RN?T??NàL?Z?T??N / ??t?rnat??nàl?z?t??n
Ruby 2.4 (lithuanian)         :      I?T?RN?TI?NàLIZ?TI?N / i?t?rnati?nàliz?ti?n
Ruby 2.4 (fold)               :                         - / i?t?rnati?nàliz?ti?n