如何将 "i" 与 java 中的土耳其语 i 匹配?

How do I match "i" with Turkish i in java?

我想将英语 (i) 的 "I" 小写与土耳其语 (i) 的小写“İ”匹配。它们是相同的字形,但不匹配。当我这样做时 System.out.println("İ".toLowerCase()); 字符 i 和一个点被打印出来(这个网站没有正确显示)

有没有办法匹配这些?(最好不用硬编码)我想让程序匹配与语言和 utf 代码无关的相同字形。这可能吗?

我测试了规范化但没有成功。

public static void main(String... a) {
    String iTurkish = "\u0130";//"İ";
    String iEnglish = "I";
    prin(iTurkish);
    prin(iEnglish);
}

private static void prin(String s) {
    System.out.print(s);
    System.out.print(" -  Normalized : " + Normalizer.normalize(s, Normalizer.Form.NFD));
    System.out.print(" - lower case: " + s.toLowerCase());
    System.out.print(" -  Lower case Normalized : " + Normalizer.normalize(s.toLowerCase(), Normalizer.Form.NFD));
    System.out.println();

}

结果没有在网站上正确显示,但第一行(iTurkish)仍然有 ̇ 接近小写的 i。

目的和问题

这将是一个多语言词典。我希望程序能够识别“İFEL”以 "if" 开头。为了确保它们不区分大小写,我首先将两个文本都转换为小写。 İFEL 变为 i(dot)fel 并且 "if" 未被识别为其中的一部分

如果您打印出您所看到的字符的十六进制值,区别就很明显了:

İ 0x130 - Normalized : İ 0x49 0x307 - Lower case: i̇ 0x69 0x307 - Lower case Normalized : i̇ 0x69 0x307
I 0x49 - Normalized : I 0x49 - Lower case: i 0x69 - Lower case Normalized : i 0x69

规范化土耳其语 İ 不会给您英语 I,而是给您英语 I 后跟变音符号 0x307。这是正确的,并且是规范化过程所期望的。规范化不是 "Convert to ASCII" 操作。作为 Normalizer mentions, the process it's following is a very rigorously defined standard, the Unicode Standard Annex #15 — Unicode Normalization Forms.

的文档

numerous ways to strip diacritics, either before or after normalizing. What you need will depend on the specifics of your use case, but for your use case I would suggest using Guava's CharMatcher class 规范化后去除非ASCII字符,例如:

String asciiString = CharMatcher.ascii().retainFrom(normalizedString);

This answer 深入探讨了 \p{InCombiningDiacriticalMarks} 的作用,以及它为何不理想。我的 CharMatcher 解决方案也不理想(链接的答案提供了更强大的解决方案),但为了快速修复,您可能会发现只保留 ASCII 字符 "good enough"。这比基于 Pattern 的方法更接近 "correct" 并且更快。

您可以使用以下代码:

public static void main(String... a) {

      String iTurkish = "\u0130";//"İ";
      String iEnglish = "I";
      prin(iTurkish);
      prin(iEnglish);


}

private static void prin(String s) {
    System.out.print(s);
    String nfdNormalizedString = Normalizer.normalize(s, Normalizer.Form.NFD);
    Pattern pattern = Pattern.compile("\p{InCombiningDiacriticalMarks}+");
    System.out.print(" -  Normalized : " + pattern.matcher(nfdNormalizedString).replaceAll(""));
    System.out.print(" - lower case: " + s.toLowerCase());
    System.out.print(" -  Lower case Normalized : " + Normalizer.normalize(pattern.matcher(nfdNormalizedString).replaceAll("").toLowerCase(), Normalizer.Form.NFD));
    System.out.println();

}

或见Converting Symbols, Accent Letters to English Alphabet