2017-02-01 55 views
4

我希望能够识别中文,日文和韩文书写字符,既可以作为一般组,也可以作为细分语言。这些都是原因:Android中区分CJK语言(中文,日文,韩文)

  • 认识到中日韩作为一般组:我想提出一个垂直脚本蒙古TextView。为此,我需要将文本行旋转90度,因为字形水平存储在字体中。但是,对于CJK语言,我需要再次将它们旋转回来,以便它们以正确的方向书写,但是只能堆叠在彼此之上。
  • 将CJK区分为特定语言:我也制作蒙古文字典,当用户输入CJK字符进行查找时,我想自动识别该语言。因为日本人和韩国人也使用汉字,所以我猜测我无法完全做到这一点,但我希望在编码允许的最大程度上做到这一点。

在语言方面,我所知道的是

为了完整起见,中国的文字也在Vietnamese使用(所以CJK也被称为CJKV)。对于我目前的目的,我不需要担心,但这可能是未来的考虑。我也忽略了像中文pinyin或日文romaji这样的罗马化脚本。它们在TextView中的处理方式与英文和蒙古文相同(即与该行的其余部分旋转90度)。在台湾使用的Bopomofo也可能是未来的考虑因素,但现在我会忽略它。有关语言示例,另请参阅herehere

我见过很多相关的问题,通常用Java或Android中的一种特定语言处理,但没有规范答案的总体问题。其他问题对于Unicode更通用,但不说明如何在Java和Android中执行此操作。这里是一些具体的。

所以我的问题是,能有多大区别我使用Unicode编码点的CJK语言,我怎么能在Android的测试呢?我已经在Java和Android上看到了一些更新的测试,虽然这些测试很有用,但我还需要支持较老的Android设备。

回答

11

统一

CJK(和CJKV)以Unicode是指汉象形文字,那就是,中国的字符中国,日本,韩国,越南和使用(汉字)。对于Unicode脚本命名,它不是而不是是指像日文片假名和平假名或韩文韩文这样的拼音脚本。汉族思想家据说是统一的。这意味着每个表意文字只有一个Unicode代码点,不管它使用哪种语言。

这意味着Unicode(反过来说Android/Java)不提供基于单个语言来确定语言的方法只有汉字。即使中文简体/繁体字也不易与编码区分开来。这与无法知道字符“a”是属于英语,法语还是西班牙语的想法是一样的。需要更多的上下文来确定。

但是,您可以使用Unicode编码来确定日文平假名/片假名和韩文朝鲜语。而这些人物的出现可以很好地表明附近的汉代文字属于同一种语言。

的Android

你可以找到一些指标与

int codepoint = Character.codePointAt(myString, offset) 

码点,如果你想iterate through the codepoints in a string

final int length = myString.length(); 
for (int offset = 0; offset < length;) { 
    final int codepoint = Character.codePointAt(myString, offset); 

    // use codepoint here 

    offset += Character.charCount(codepoint); 
} 

一旦你的代码点你可以看一下它的代码它与

Character.UnicodeBlock block = Character.UnicodeBlock.of(codepoint); 

然后您可以使用代码块来测试表意文字或语言。

CJK

扫描Unicode代码块,我想这些覆盖所有CJK汉字。如果我错过了,请随时编辑我的答案或留下评论。

private boolean isCJK(int codepoint) { 
    Character.UnicodeBlock block = Character.UnicodeBlock.of(codepoint); 
    return (
      Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS.equals(block)|| 
      Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A.equals(block) || 
      Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B.equals(block) || 
      Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C.equals(block) || // api 19 
      Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D.equals(block) || // api 19 
      Character.UnicodeBlock.CJK_COMPATIBILITY.equals(block) || 
      Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS.equals(block) || 
      Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS.equals(block) || 
      Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT.equals(block) || 
      Character.UnicodeBlock.CJK_RADICALS_SUPPLEMENT.equals(block) || 
      Character.UnicodeBlock.CJK_STROKES.equals(block) ||      // api 19 
      Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION.equals(block) || 
      Character.UnicodeBlock.ENCLOSED_CJK_LETTERS_AND_MONTHS.equals(block) || 
      Character.UnicodeBlock.ENCLOSED_IDEOGRAPHIC_SUPPLEMENT.equals(block) || // api 19 
      Character.UnicodeBlock.KANGXI_RADICALS.equals(block) || 
      Character.UnicodeBlock.IDEOGRAPHIC_DESCRIPTION_CHARACTERS.equals(block)); 
} 

与评论(向右滚动)中的那些只能从API级别19.然而,这些也许可以安全删除,如果你需要支持早期版本的,因为他们只是很少使用。另外,Unicode定义了一个CJK扩展E,但是在编写本文时,它在Android/Java中不受支持。如果您确实需要包含所有内容,则可以直接将代码点与Unicode块范围进行比较。 This site is a convenient place to browse them.你也可以在Unicode site看到它们。

如果您不需要在API 19下面支持,那么isIdeographic会使测试变得非常简单(尽管我不知道它是否返回与上述方法完全相同的匹配项)。

private boolean isCJK(int codepoint) { 
    return Character.isIdeographic(codepoint); 
} 

或者这一个API 24+:

private boolean isCJK(int codepoint) { 
    return (Character.UnicodeScript.of(codepoint) == Character.UnicodeScript.HAN); 
} 

日本

为了测试平假名或片假名这应该很好地工作:如果你

private boolean isJapaneseKana(int codepoint) { 
    Character.UnicodeBlock block = Character.UnicodeBlock.of(codepoint); 
    return (
      Character.UnicodeBlock.HIRAGANA.equals(block) || 
      Character.UnicodeBlock.KATAKANA.equals(block) || 
      Character.UnicodeBlock.KATAKANA_PHONETIC_EXTENSIONS.equals(block)); 
} 

或者这支持API 24+:

(这需要更多的测试。如有必要,下面见注释)。

private boolean isJapaneseKana(int codepoint) { 
    return (Character.UnicodeScript.of(codepoint) == Character.UnicodeScript.HIRAGANA || 
      Character.UnicodeScript.of(codepoint) == Character.UnicodeScript.KATAKANA); 
} 

韩国

为了测试韩语较低的API,你可以使用

private boolean isKoreanHangul(int codepoint) { 
    Character.UnicodeBlock block = Character.UnicodeBlock.of(codepoint); 
    return (Character.UnicodeBlock.HANGUL_JAMO.equals(block) || 
      Character.UnicodeBlock.HANGUL_JAMO_EXTENDED_A.equals(block) || // api 19 
      Character.UnicodeBlock.HANGUL_JAMO_EXTENDED_B.equals(block) || // api 19 
      Character.UnicodeBlock.HANGUL_COMPATIBILITY_JAMO.equals(block) || 
      Character.UnicodeBlock.HANGUL_SYLLABLES.equals(block)); 
} 

删除线标记API 19。

或为API 24+:

private boolean isKoreanHangul(int codepoint) { 
    return (Character.UnicodeScript.of(codepoint) == Character.UnicodeScript.HANGUL); 
} 

进一步研究

+0

嗨,好像你的API 24+ isJapanese方法不承认作为ーkatanka – tObi

+0

@tObi,谢谢你离开这个评论。我还没有在我的任何生产项目中使用API​​ 24+代码,因为我仍然需要支持API 24,所以我没有遇到你提到的问题。如果你发现什么是错的或如何解决它,请留下另一条评论。 – Suragch

+0

@tObi,为了我的测试目的,你能告诉我一个没有被识别的特定片假名角色吗? – Suragch

相关问题