Diferenciación de los lenguajes CJK (chino, japonés y coreano) en Android

Quiero ser capaz de reconocer caracteres chinos, japoneses y coreanos escritos, tanto como un grupo general y como lenguajes subdivididos. Estas son las razones:

  • Reconozca CJK como un grupo general: Estoy haciendo un script vertical Mongolian TextView . Para ello necesito girar la línea de texto 90 grados porque los glifos se almacenan horizontalmente en la fuente. Sin embargo, para los lenguajes CJK, necesito rotarlos de nuevo para que se escriban en su orientación correcta, pero simplemente apilados uno encima del otro por la línea.
  • Diferenciar CJK en lenguajes específicos: También estoy haciendo un diccionario mongol y cuando los usuarios introducen un carácter CJK para buscar, me gustaría reconocer automáticamente el idioma. Debido a que los caracteres chinos también son utilizados por los japoneses y los coreanos, estoy adivinando que no será capaz de lograr plenamente esto, pero quiero hacerlo en la medida máxima que la codificación permite.

Desde el punto de vista lingüístico, las subcategorías que conozco son

  • Personajes tradicionales chinos
  • Caracteres simplificados chinos
  • Kanji japonés (caracteres chinos)
  • Hiragana japonés (alfabeto nativo)
  • Katakana japonés (alfabeto para escribir palabras extranjeras)
  • Coreano Hangul (fonético)
  • Hanja coreano (caracteres chinos)

En aras de la integridad, los caracteres chinos también se utilizan en vietnamita (por lo que CJK también se llama CJKV). Para mis propósitos actuales no necesito preocuparme de él, pero podría ser una consideración futura. También estoy ignorando scripts romanizados como pinyin chino o romaji japonés. Serán manejados igual que inglés y mongol en el TextView (es decir, girado 90 grados con el resto de la línea). Bopomofo utilizado en Taiwán también podría ser una consideración futura, pero voy a ignorar por ahora. Vea también aquí y aquí para ejemplos de idiomas.

He visto una serie de preguntas relacionadas que suelen tratar con un lenguaje específico en Java o Android, pero ninguna pregunta general con una respuesta canónica. Otras preguntas son más generales para Unicode, pero no explican cómo hacerlo en Java y Android. Éstos son algunos de los específicos.

  • ¿Cómo comprobar si el texto dado es inglés o chino en android?
  • ¿Cómo puedo detectar texto japonés en una cadena de Java?
  • Compruebe si la cadena contiene caracteres CJK (chinos)
  • Utilice la expresión regular para coincidir con cualquier carácter chino en utf-8 de codificación
  • Prueba de caracteres japoneses / chinos en una cadena
  • Representación diferente de los puntos de código unicode en japonés y chino
  • Compruebe si un personaje es chino tradicional en Big-5 (Java)?
  • Caracteres Unicode necesarios para japonés, coreano y chino
  • ¿Los mismos caracteres chinos compartidos por cjk comparten el mismo valor unicode?
  • ¿Cuál es el rango completo de caracteres chinos en Unicode?

Así que mi pregunta es, ¿cuánto puedo diferenciar los lenguajes CJK usando Unicode codepoints y cómo puedo probarlos en Android? He visto algunas pruebas más nuevas en Java y Android, y aunque estas son útiles de saber, también necesito soportar dispositivos Android más antiguos.

Unicode

CJK (y CJKV) en Unicode se refiere a los ideogramas Han, es decir, los caracteres chinos (汉字) utilizados en chino, japonés, coreano y vietnamita. Para el nombre de script Unicode, no se refiere a los scripts fonéticos escritos como Katakana japonesa y Hiragana o Hangul coreano. Se dice que los ideogramas Han están unificados. Con esto significan que sólo hay un codigo Unicode para cada ideograma, sin importar el idioma en el que se use.

Esto significa que Unicode (y viceversa Android / Java) no proporciona ninguna forma de determinar el lenguaje basado en un único ideograma. Incluso los caracteres simplificados / tradicionales chinos no se diferencian fácilmente de la codificación. Esta es la misma idea de no ser capaz de saber si el carácter "a" pertenece al inglés, francés o español. Se necesita más contexto para determinar eso.

Sin embargo, puede utilizar la codificación Unicode para determinar Hiragana japonés / Katakana y Hangul coreano. Y la presencia de tales caracteres sería una buena indicación de que los ideógrafos Han cercanos pertenecen al mismo idioma.

Androide

Puede encontrar el código en algún índice con

 int codepoint = Character.codePointAt(myString, offset) 

Y si quisieras iterar a través de los codepoints en una cadena :

 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); } 

Una vez que tenga el codepoint, puede buscar el bloque de código en el que está

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

Y entonces usted puede usar el código para probar el ideograma o el lenguaje.

CJK

Escaneando los bloques de código Unicode, creo que estos cubren todos los ideogramas CJK. Si me perdí alguno, entonces no dude en editar mi respuesta o dejar un comentario.

 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)); } 

Los que tienen comentarios (desplazarse a la derecha) sólo están disponibles desde el nivel API 19. Sin embargo, probablemente podrían eliminarse de forma segura si necesita admitir versiones anteriores ya que sólo se utilizan con poca frecuencia. Además, Unicode define una CJK Extension E, pero en el momento de escribir esto no es compatible con Android / Java. Si definitivamente necesita incluir todo, entonces puede comparar los codepoints con los rangos de bloques Unicode directamente. Este sitio es un lugar conveniente para navegar por ellos. También puede verlos en el sitio de Unicode .

Si no necesita soportar por debajo de la API 19, isIdeographic hace la prueba muy fácil (aunque no sé si devuelve exactamente los mismos coincidencias que el método anterior).

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

O éste para API 24+:

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

japonés

Para probar Hiragana o Katakana esto debería funcionar bien:

 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)); } 

O esto si usted está apoyando la API 24+:

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

coreano

Para probar Hangul en APIs más bajas puedes usar

 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)); } 

Elimine las líneas marcadas API 19 si es necesario.

O para API 24+:

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

Estudio adicional

  • Scripts de Asia Oriental de Unicode
  • Preguntas frecuentes de Unicode CJK
  • Preguntas frecuentes sobre el coreano de Unicode
  • Algún código fuente que muestra cómo funciona Character.UnicodeScript
  • CJK Unified Ideographs
  • Letras cirílicas que no se muestran en PDF generadas con iText en Android
  • Android TextView measureText para el árabe
  • Recibe la entrada completa de unicode android en C / C ++
  • Personajes japoneses que parecen chinos en Android
  • ¿Hay algún carácter unicode que tiene el glifo que falta en todas las fuentes?
  • Añada marca (✔) a string.xml
  • El archivo kcm de Android no parece funcionar. ¿Qué me estoy perdiendo?
  • Cómo establecer emoji por unicode en android textview
  • Deteniendo texto de división a varias líneas en los períodos en direcciones web
  • No se pudo encontrar la clase 'android.graphics.drawable.RippleDrawable' Unicode issue?
  • ¿Cómo puedo mostrar símbolos fonéticos (IPA) en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.