ICU Transliteration Katakana滤波器不适用于半宽片假名声音标记

时间:2015-09-11 13:40:46

标签: java unicode icu

我正在尝试使用ICU Transliterator对某些文本进行非常具体的转换,如here所述。

我的文字包含半角片假名字符和常规拉丁字符。我想将半宽片假名转换为全宽片假名,同时保持非片假名字符不变。

我想简单地应用标准" Halfwidth-Fullwidth" ICU转换与仅选择片假名的过滤器,这不起作用 - 片假名过滤器不适用于Halfwidth Katakana Voiced Sound Mark,这让我感到惊讶。我试图弄清楚这是出于预期还是一个错误。

有关示例,请参阅以下代码。我试过了:

  1. 没有过滤器的半宽全宽 - 影响太大
  2. 使用片假名过滤器的半宽全宽 - 没有影响U + ff9e - 这是一个错误吗?
  3. 带有负拉丁滤波器的半宽全宽 - 仍受影响的空间。
  4. 带复合负滤波器的半宽全宽 - 太脆弱了。
  5. 有什么想法吗? 有什么地方我可以检查ICU [:Katakana:]过滤器中实际包含哪些字符?

    void transliterateWithRules(String original, String rules) {
        Transliterator transliterator = Transliterator.createFromRules("mytest", rules, Transliterator.FORWARD);
        String result = transliterator.transliterate(original);
        System.out.println(String.format("Transliteration result: \"%s\", codepoints: %s", result, toCodepoints(result)));
    }
    
    void test() {
        String input = "ギ a"; // Unicode Codepoints: \uff77 \uff9e \u20 \u61
    
        transliterateWithRules(input, ":: Halfwidth-Fullwidth;");
        // Result:
        // "ギ a", codepoints: \u30ae \u3000 \uff41
        // This makes everything fullwidth, including the space and the latin 'a'
    
        transliterateWithRules(input, "::  [:Katakana:]; :: Halfwidth-Fullwidth;");
        // Result:
        // "ギ a", codepoints: \u30ad \uff9e \u20 \u61
        // This makes the Katakana KI fullwidth, and skips the space and 'a' as intended, but it also
        // skips the Halfwidth Katakana Voiced Sound Mark (U+FF9E), which I expected to be converted.
    
        transliterateWithRules(input, ":: [:^Latin:] Halfwidth-Fullwidth;");
        // Result:
        // "ギ a", codepoints: \u30ae \u3000 \u61
        // Skips the latin 'a' as intended, but makes the space Fullwidth, which I don't want
    
        transliterateWithRules(input, ":: [[:^Latin:]&[^\\ ]]; :: Halfwidth-Fullwidth;");
        // Result:
        // "ギ a", codepoints: \u30ae \u20 \u61
        // Exactly what I want, for this example - but relying on a list of exclusions is fragile, since I am only
        // excluding what I currently know about.
    }
    

2 个答案:

答案 0 :(得分:2)

您可以在[:Katakana:]here中看到一个字符列表,其中既不包含U+FF9E也不包含U+FF9F

这是因为[:Katakana:]相当于[:Script=Katakana:],它会测试角色的"Script" propertyU+FF9EU+FF9F都被标记为在平假名片假名文本中使用,因此他们的脚本属性为" Common" (而不是像这样的东西,它只是"片假名")。有一个"脚本扩展"包含两个脚本的属性,但[:Katakana:]未对其进行检查。

您可以手动将它们添加到集合([[:Katakana:]\uFF9E\uFF9F]),也可以创建包含脚本扩展的集合:

[\p{sc=Katakana}\p{scx=Katakana}]

(请注意,这也包含一些其他共享字符。)

答案 1 :(得分:0)

通过浏览ICU代码(CjkBreakEngine.java:26),我注意到使用了以下模式:

fKatakanaWordSet.applyPattern("[[:Katakana:]\\uff9e\\uff9f]");

基于此,可能是故意不包括这些声音标记,我不知道为什么。