Trabajar con Unicode en JavaScript – Parte 1

Lo primero que se aprende en cualquier lenguaje de programación es a crear e imprimir cadenas de texto (strings) con el típico Hola Mundo. En este artículo vamos a profundizar un poco más en las strings, en qué hay realmente por detrás y cómo las entienden las máquinas. En la segunda parte veremos como trabajar con Unicode en JavaScript

Empecemos por abajo, el sistema binario

Los ordenadores almacenan, procesan y comparten la información con un sistema de codificación basado en dos símbolos, normalmente se utiliza el dígito 1 para representar el nivel alto (o activo) y el dígito 0 para el nivel bajo (o apagado). Una unidad de información se llama bit, y puede tomar el valor 1 o 0. Cuando hablamos de almacenamiento o espacio se agrupan en conjuntos de 8, lo que forma un byte.

A lo mejor te parece raro, ya que en tu ordenador o en tu teléfono tienes muchos tipos distintos de archivos, ya sean fotos, textos, audios o vídeos. En el fondo todos estos archivos no son más que sucesiones muy muy largas de 1s y 0s que tu dispositivo al abrirlos decide cómo representarlos para hacerlo correctamente, ya sea por metadatos que haya en los propios archivos o por la propia extensión del nombre de archivo. ¿Has probado a abrir una imagen con el bloc de notas?

Unicode

¿Cómo pasamos de 1 y 0 a letras?

Unicode es un estándar para representar todos los símbolos que usamos en nuestros dispositivos (letras, números, emojis, símbolos matemáticos etc…). Para ello se le asigna a cada carácter o símbolo un nombre inequívoco y un número que se conoce como punto de código (code point) y se suele representar en hexadecimal. Algunos ejemplos son:

  • carácter – nombre – punto de código
  • A – Latin Capital Letter A – 0041
  • a – Latin Small Letter A – 0061
  • á – Latin Small Letter a with Acute – 00E1
  • 💩 – Pile of Poo Emoji – 1F4A9

Puede que te estés preguntando cuántos símbolos hay en unicode. Los puntos de código van desde 0000 hasta 10FFFF, lo que se traduce en más de 1.1 millones de símbolos, aunque no se usan todos.

Unicode organiza los símbolos en planos, el primero va desde el 0000 hasta el FFFF y se le conoce como BMP (Basic Multilingual Plane). Es el plano que contiene los símbolos más usados y desde el 0000 hasta el 007F coincide con ASCII. Al resto de planos al parecer se les conoce como planos astrales, aunque han quitado la referencia de la wikipedia.

Hay que tener en cuenta que Unicode no es un sistema de codificación, simplemente es un sistema por el cual cada símbolo ya tiene un número asociado, pero teniendo esos números ahora sí que podemos convertirlos en binario con un sistema de codificación.

Codificaciones de Unicode: UTF-8, UTF-16, UTF-32

El sistema de codificación estándar de Unicode es UTF (Unicode Transformation Format) y tiene distintas variantes, aunque las más usadas son UTF-8 y UTF-16.

Se trata de sistemas de codificación de longitud variable, UTF-8 usa de uno a cuatro bytes para representar todo el espacio Unicode, mientras que UTF-16 utiliza uno o dos conjuntos de 16 bits (dos a cuatro bytes).

De momento no vamos a profundizar más en la codificación, simplemente tendremos en cuenta que Javascript usa UTF-16, o en versiones antiguas UCS-2 (2-byte Universal Character Set, que es una versión anterior de UTF-16 con una longitud fija de 16 bits.

Equivalencia de unicode

La equivalencia de unicode es una especificación por la que algunos símbolos se pueden definir de dos maneras, con un punto de código como ya hemos visto, y otra en la que varios carácteres seguidos se representan como un único símbolo.

Tomemos el ejemplo del símbolo «á» que hemos visto antes, su punto de código es el 00E1. Otra manera de representar ese carácter sería con el símbolo «a» (0061) seguido del símbolo Combining Acute Accent «´» (0301). Ten en cuenta que existe el símbolo Acute Accent (00B4) y que si ponemos la letra a seguida de este símbolo no se combinarán. Para combinar símbolos están hay que ir al símbolo equivalente para combinar, cuyo nombre normalmente empezará por Combining.

Estas dos maneras de representar el mismo carácter puede hacer que estemos buscando en un texto una palabra y que no la encontremos, porque aunque visualmente el glifo es el mismo, realmente los carácteres unicode no son iguales. En el siguiente artículo entenderemos esto cuando hablemos de unicode y JavaScript.

Normalización

La manera que tenemos para solventar el problema anterior de búsqueda es la normalización. Se trata de un proceso por el cual se unifica la forma de codificar los símbolos. La normalización puede ser por equivalencia canónica o equivalencia de compatibilidad.

La equivalencia canónica sería el caso anterior de la letra a con acento, mientras que la equivalencia por compatibilidad se trata de carácteres que, con distinta forma, representan el mismo significado del símbolo, un ejemplo sería el símbolo ℌ que es compatible con la letra H.

Tenemos además dos formas de normalización, por composición o por descomposición. En ambos casos el proceso empieza por descomponer el texto, ya sea por equivalencia canónica o de compatibilidad, y luego ordenar o recomponer los símbolos con la equivalencia canónica. De esta manera salen las cuatro formas de normalizar:

  • NFD (Normalization Form Canonical Decomposition): Los símbolos se descomponen por equivalencia canónica, y los carácteres múltiples se ordenan en un determinado orden
  • NFC (Normalization Form Canonical Composition): Los símbolos se descomponen igual por equivalencia canónica y luego se vuelven a componer con la equivalencia canónica
  • NFKD (Normalization Form Compatibility Decomposition): Los símbolos se descomponen por compatibilidad y los carácteres múltiples se ordenan en un orden específico.
  • NFKC (Normalization Form Compatibility Composition): Los símbolos se descomponen y componen por compatibilidad y se vuelven a componer por forma canónica

Si quieres profundizar mas en el tema te recomiendo esta sección en la web de unicode https://unicode.org/reports/tr15/#Canon_Compat_Equivalence

Emojis

Una vez hemos entendido como funciona Unicode podemos adentrarnos en el apasionante mundo de los emojis. Un emoji no es mas que un símbolo, al igual que una letra o un número. Pero hay dos tipos de emoji, los que tienen un punto de código propio, como podría ser Family 👪 (1F46A) o los que se forman por composición de otros emojis 🤯 (este no, este tiene el punto de código 1F92F), como podría ser esta otra familia 👨‍👩‍👧‍👦 compuesta por 👨 (1F468), 👩 (1F469), 👧 (1F467), 👦 (1F466).

Composición de Emojis

Antes hemos visto como hay símbolos que tienen su forma normal y luego un carácter para combinar, pero en el caso de los emojis no funciona así. Para combinar emojis se utiliza el símbolo unicode Zero Width Joiner (200D), un símbolo que no ocupa espacio pero se usa para unir los emojis. Cuando tenemos un emoji formado por una secuencia de otros emojis se le llama secuencia ZWJ y tienes un listado en la emojipedia con todas las posibles combinaciones.


Con esto llegamos al final del primer artículo, hemos explicado Unicode y cómo funciona, en la siguiente entrada veremos su uso en JavaScript y un poco de uso avanzado aprovechando este conocimiento.

Fuentes

A parte de todos los enlaces puesto en la entrada, aquí te dejo alguno más que me han servido mucho para entender realmente cómo funciona unicode

Un comentario en «Trabajar con Unicode en JavaScript – Parte 1»

Deja una respuesta

Tu dirección de correo electrónico no será publicada.