【问题标题】:Transliteration in ruby红宝石音译
【发布时间】:2010-12-16 03:11:08
【问题描述】:

在ruby中音译非英文字符的最简单方法是什么。也就是这样的转换:

translit "Gévry"
#=> "Gevry"

【问题讨论】:

标签: ruby transliteration


【解决方案1】:

使用 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”,可以用两种方式表示:

  • é = U+00E9
  • é = (e = U+0065) + (急性 = U+0301)

第一种形式是最流行的单个代码点。第二种形式是分解格式,将字素(在屏幕上显示为“é”)分成两个基本代码点,即 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 字母。

【讨论】:

  • +1 用于分离字母重音然后删除它们的巧妙方法。 -1 表示不将 'ı' 标准化为 'i'
【解决方案2】:

尝试查看来自 TechniConseils 的 this script,它替换了字符串中的重音字符。用法示例:

"Gévry".removeaccents #=> Gevry

【讨论】:

    【解决方案3】:

    Ruby 在其标准库中有一个 Iconv 库,它以与通常的 iconv 命令非常相似的方式转换编码

    【讨论】:

    • 是的.. Iconv.iconv('ascii//ignore//translit', 'utf-8', string).to_s 完成了这项工作。
    • 我刚刚在 OP 的示例中尝试了这个,它返回“Gvry”,而不是“Gevry”。
    • @jrdioko 应该是Iconv.iconv('ascii//translit//ignore', 'utf-8', string)
    • 您需要使用Iconv.conv 方法而不是Iconv.iconv
    • Iconv.iconv 将被弃用,你如何使用 String#encode 来进行这种音译?
    猜你喜欢
    • 1970-01-01
    • 2011-08-02
    • 1970-01-01
    • 2019-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-09
    • 1970-01-01
    相关资源
    最近更新 更多