Enquanto desenvolvia um contador de caracteres para meu site, descobri que diferentes linguagens de programação contavam caracteres de maneiras diferentes. O problema se agravou quando o front-end e o back-end usavam regras diferentes para validar o tamanho do texto. Este guia aborda as diferentes medidas de caracteres e como normalizar e cortar texto para evitar problemas.

Quantos caracteres tem "Ação 👍🏽"? JavaScript diz 9, Python diz 7

Bytes (UTF-8)

O PHP, por exemplo, conta os bytes em UTF-8. Cada caractere Unicode em UTF-8 ocupa um número de bytes variável, e caracteres como 'ç' e 'ã' ocupam 2 bytes cada. Emojis, que ocupam 4 bytes cada, são contados como um único caractere. Por exemplo, 'Ação 👍🏽'.length em PHP é 15, pois cada emoji é contado como um caractere.

Unidades UTF-16

O JavaScript e o Java, por outro lado, contam caracteres em unidades UTF-16, que são pedaços de 16 bits. Cada caractere Unicode em UTF-16 ocupa 2 unidades UTF-16, e emojis, que ocupam mais de 16 bits, são contados como dois pedaços. Por exemplo, 'Ação 👍🏽'.length em JavaScript é 9, pois cada emoji é contado como dois pedaços.

Code Points (Unicode)

O Python e o PHP, por sua vez, contam caracteres Unicode diretamente, ou seja, o número de caracteres Unicode é contado. Por exemplo, 'Ação 👍🏽'.length em Python é 7, pois cada caractere Unicode é contado como um caractere.

Grafemas (Unicode)

O texto é normalmente dividido em grafemas, que são unidades de escrita que podem ser reconhecidos como um único caractere. Em emojis, por exemplo, o polegar e o tom de pele são grafemas separados. O texto 'Ação 👍🏽' é normalmente dividido em três grafemas: 'Ação', '👍', e '🏽'.

Normalização

Para garantir que o texto seja sempre igual, é importante normalizar o texto antes de comparar ou salvar. Em JavaScript, isso pode ser feito usando o método normalize('NFC'). Em Python, isso pode ser feito usando o método unicodedata.normalize('NFC'). Normalizando o texto pode evitar problemas como a quebra de emojis.

Cortando Texto

Quando cortamos texto, é importante cortar por grafemas, não por caracteres individuais. Em JavaScript, isso pode ser feito usando o método slice(), mas isso pode causar problemas com emojis. Em Python, isso pode ser feito usando o método split(), que corta o texto em grafemas. Em ambos os casos, o texto cortado pode ser normalizado usando normalize('NFC') para garantir que o texto seja sempre igual.

Limites de Banco de Dados e APIs

Quando limitamos um campo em um banco de dados ou em uma API, é importante usar o mesmo limite de caracteres ou code points que a pessoa vê. Em JavaScript, isso pode ser feito usando o método length, que contará caracteres individuais. Em Python, isso pode ser feito usando o método len(), que contará code points. Em ambos os casos, é importante verificar a documentação para garantir que estamos usando o limite correto.

Conclusão

Ao desenvolver sistemas de texto, é crucial entender como diferentes medidas de caracteres podem causar problemas e como normalizar e cortar texto para evitar quebra de emojis. Ao usar o mesmo limite de caracteres ou code points no front-end e no back-end, podemos evitar problemas e garantir que o texto seja sempre igual e quebrado corretamente.

Você já tomou um erro desses em produção? Conta nos comentários.

AcaoCaracteresJavascriptPythonQuantos