【发布时间】:2010-12-16 03:11:08
【问题描述】:
在ruby中音译非英文字符的最简单方法是什么。也就是这样的转换:
translit "Gévry"#=> "Gevry"
【问题讨论】:
-
这似乎与我之前的问题完全相同:stackoverflow.com/questions/225471/…
标签: ruby transliteration
在ruby中音译非英文字符的最简单方法是什么。也就是这样的转换:
translit "Gévry"#=> "Gevry"
【问题讨论】:
标签: ruby transliteration
使用 UnicodeUtils 宝石。这适用于 1.9 和 2.0。 Iconv 在这些版本中已被弃用。
gem install unicode_utils
然后在 IRB 中试试这个:
2.0.0p0 :001 > require 'unicode_utils' #=> true
2.0.0p0 :002 > r = "Résumé" #=> "Résumé"
2.0.0p0 :003 > r.encoding #=> #<Encoding:UTF-8>
2.0.0p0 :004 > UnicodeUtils.nfkd(r).gsub(/(\p{Letter})\p{Mark}+/,'\\1')
#=> "Resume"
现在解释一下它是如何工作的!
首先你必须以NFKD(规范化形式(K)兼容性分解)格式规范化字符串。 “é” unicode 代码点,称为“latin small letter e with acute”,可以用两种方式表示:
第一种形式是最流行的单个代码点。第二种形式是分解格式,将字素(在屏幕上显示为“é”)分成两个基本代码点,即 ASCII“e”和重音符号。 Unicode 可以由许多代码点组成一个字素,这在某些亚洲书写系统中很有用。
请注意,您通常希望将数据标准化为标准格式以进行比较、排序等。在 ruby 中,这里的“é”的两种格式不等于()。在 IRB 中,这样做:
> "\u00e9" #=> "é"
> "\u0065\u0301" #=> "é"
> "\u00e9" == "\u0065\u0301" #=> false
> "\u00e9" > "\u0065\u0301" #=> true
> "\u00e9" >= "f" #=> true (composed é > f)
> "\u0065\u0301" > "f" #=> false (decomposed é < f)
> "Résumé".chars.count #=> 6
> decomposed = UnicodeUtils.nfkd("Résumé")
#=> "Résumé"
> decomposed.chars.count #=> 8
> decomposed.length #=> 6
> decomposed.gsub(/(\p{Letter})\p{Mark}+/,'\\1')
#=> "Resume"
现在我们有了 NFKD 格式的字符串,我们可以使用“属性名称”语法 (\p{property_name}) 应用正则表达式来匹配一个字母后跟一个或多个变音符号“标记”。通过捕获匹配的字母,我们可以使用 gsub 将字母+变音符号替换为整个字符串中捕获的字母。
此技术从 ASCII 字母中删除了变音符号,并且不会将字符集(如希腊语或西里尔语字符串)音译为等效的 ASCII 字母。
【讨论】:
尝试查看来自 TechniConseils 的 this script,它替换了字符串中的重音字符。用法示例:
"Gévry".removeaccents #=> Gevry
【讨论】:
Ruby 在其标准库中有一个 Iconv 库,它以与通常的 iconv 命令非常相似的方式转换编码
【讨论】:
Iconv.iconv('ascii//ignore//translit', 'utf-8', string).to_s 完成了这项工作。
Iconv.iconv('ascii//translit//ignore', 'utf-8', string)
Iconv.conv 方法而不是Iconv.iconv。