ICU 音译片假名过滤器不适用于半角片假名浊音标记
ICU Transliteration Katakana filter not applying to Halfwidth Katakana Voiced Sound Mark
我正在尝试使用 ICU Transliterator 对某些文本进行非常具体的转换,如 here 所述。
我的文字包含半角片假名字符和常规拉丁字符。我想将半角片假名转换为全角片假名,同时保持非片假名字符不变。
我想简单地将标准 "Halfwidth-Fullwidth" ICU 转换与仅选择片假名的过滤器一起应用,但这没有用 - 片假名过滤器不适用于 Halfwidth Katakana Voiced Sound Mark,这让我感到惊讶我。我想弄清楚这是有意为之还是错误。
有关示例,请参见下面的代码。我试过了:
- 没有过滤器的半宽-全宽 - 影响太大
- 带片假名过滤器的半宽-全宽 - 不影响 U+ff9e - 这是一个错误吗?
- 具有负拉丁语过滤器的半宽-全宽 - 仍然影响空格。
- 带复合负滤镜的半宽-全宽 - 太脆弱了。
有什么想法吗?
有什么地方可以检查 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.
}
通过浏览 ICU 代码 (CjkBreakEngine.java:26),我注意到使用了以下模式:
fKatakanaWordSet.applyPattern("[[:Katakana:]\uff9e\uff9f]");
基于此,可能有意不包含这些声音标记,虽然我也说不出原因。
您可以看到 [:Katakana:]
集合 here 中的字符列表,其中既不包含 U+FF9E
也不包含 U+FF9F
。
这是因为[:Katakana:]
等同于[:Script=Katakana:]
,它测试一个字符的"Script" property。 U+FF9E
和 U+FF9F
都被标记为在平假名 和 片假名文本中使用,因此它们的脚本 属性 是 "Common"(而不是类似于 キ
,完全是 "Katakana")。有一个包含两个脚本的 "Script Extensions" 属性,但是 [:Katakana:]
没有检查它。
您可以手动将它们添加到集合中 ([[:Katakana:]\uFF9E\uFF9F]
),或者创建一个包含脚本扩展的集合:
[\p{sc=Katakana}\p{scx=Katakana}]
(请注意,这也包含一些其他共享字符。)
我正在尝试使用 ICU Transliterator 对某些文本进行非常具体的转换,如 here 所述。
我的文字包含半角片假名字符和常规拉丁字符。我想将半角片假名转换为全角片假名,同时保持非片假名字符不变。
我想简单地将标准 "Halfwidth-Fullwidth" ICU 转换与仅选择片假名的过滤器一起应用,但这没有用 - 片假名过滤器不适用于 Halfwidth Katakana Voiced Sound Mark,这让我感到惊讶我。我想弄清楚这是有意为之还是错误。
有关示例,请参见下面的代码。我试过了:
- 没有过滤器的半宽-全宽 - 影响太大
- 带片假名过滤器的半宽-全宽 - 不影响 U+ff9e - 这是一个错误吗?
- 具有负拉丁语过滤器的半宽-全宽 - 仍然影响空格。
- 带复合负滤镜的半宽-全宽 - 太脆弱了。
有什么想法吗?
有什么地方可以检查 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.
}
通过浏览 ICU 代码 (CjkBreakEngine.java:26),我注意到使用了以下模式:
fKatakanaWordSet.applyPattern("[[:Katakana:]\uff9e\uff9f]");
基于此,可能有意不包含这些声音标记,虽然我也说不出原因。
您可以看到 [:Katakana:]
集合 here 中的字符列表,其中既不包含 U+FF9E
也不包含 U+FF9F
。
这是因为[:Katakana:]
等同于[:Script=Katakana:]
,它测试一个字符的"Script" property。 U+FF9E
和 U+FF9F
都被标记为在平假名 和 片假名文本中使用,因此它们的脚本 属性 是 "Common"(而不是类似于 キ
,完全是 "Katakana")。有一个包含两个脚本的 "Script Extensions" 属性,但是 [:Katakana:]
没有检查它。
您可以手动将它们添加到集合中 ([[:Katakana:]\uFF9E\uFF9F]
),或者创建一个包含脚本扩展的集合:
[\p{sc=Katakana}\p{scx=Katakana}]
(请注意,这也包含一些其他共享字符。)