Mostrando entradas con la etiqueta encoding. Mostrar todas las entradas
Mostrando entradas con la etiqueta encoding. Mostrar todas las entradas

viernes, 22 de diciembre de 2023

Configurando Elasticsearch para que no distinga tildes o eñes

Típico problema, indexamos un documento con el texto "Menganita conduce un camión", buscamos "camion", sin la tilde, y no aparece el documento.

Basado en este artículo: https://sacavix.com/2020/10/elasticsearch-para-espanol-acentos-y-raiz-de-palabras/


Receta rápida

1. Reconfiguramos el índice que nos interese:

curl -XPUT http://localhost:9200/_template/miindicetemplate -H "Content-Type: application/json" -d '
{
  "index_patterns": "miindice",
  "settings": {
    "number_of_shards": 2,
    "number_of_replicas": 1,
    "analysis": {
      "analyzer":{
      "mianalizador": {
          "tokenizer": "standard",
          "filter":  [ "lowercase", "asciifolding", "default_spanish_stopwords", "default_spanish_stemmer" ]
      }
    },
    "filter" : {
        "default_spanish_stemmer" : {
            "type" : "stemmer",
            "name" : "spanish"
        },
        "default_spanish_stopwords": {
            "type":        "stop",
            "stopwords": [ "_spanish_" ]
        }
    }
   }
  },
  "mappings": {
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "mianalizador",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "leadIn": {
          "type": "text",
          "analyzer": "mianalizador",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "author": {
          "type": "text",
          "analyzer": "mianalizador",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "pretitle": {
          "type": "text",
          "analyzer": "mianalizador",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
}'

2. Borramos el índice

curl -X DELETE http://localhost:9200/miindice



3. Indexamos de nuevo el contenido. Si es un proyecto Symfony con FOSElastica:

symfony console fos:elastica:reset
symfony console fos:elastica:populate

miércoles, 19 de junio de 2013

UTF8 sí o sí

Función susceptible de mejora, pero extremadamente útil.

/**
* Sirve en UTF-8 sí o sí.
*/
function supericonv($txt) {
    $txt1 = iconv('ISO-8859-15', 'UTF-8', $txt);
    $retVal = strpos($txt1, 'Ã') === FALSE ? $txt1 : $txt;
    $retVal = str_replace(array("¿", "»", "«"), array("¿", "»", "«"), $retVal);
    return $retVal;
}

lunes, 5 de abril de 2010

Conversiones entre "encodings" sin pérdidas

Hace un tiempo comentaba los problemas que surgían cuando se trabaja con diferentes "encoding".
Lo más seguro hoy en día es trabajar con el mismo "encoding" en todas las capas y sistemas: bases de datos, ficheros php, plantillas html, ficheros js, configuración del servidor web, ...
Lo malo es que no siempre esto es posible. Muchas veces tenemos que integrar contenidos o hacer que dos sistemas diferentes interaccionen y cada uno puede estar configurado de diferente manera.
Para estas tareas de conversión, existen muchas herramientas y funciones. Por ejemplo, en PHP tenemos la función iconv(). Es muy sencilla de utilizar:
string iconv ( string $in_charset , string $out_charset , string $str )

El problema que surge a menudo es cuando estamos pasando de un encoding más "rico" (p. ej., UTF-8) a otro más restringido en caracteres (p. ej., ISO-8859-1). Si se aplica la función sin más, se nos puede cortar la cadena que estamos convirtiendo cuando se encuentra con un carácter extraño al "encoding" de destino (las famosas "comillas tipográficas" de los procesadores de texto, por ejemplo, dan muchos problemas).
Afortunadamente, la función iconv() está preparada para estos casos. Si se utiliza el parámetro $out_charset con la cadena //TRANSLIT, los caracteres problemáticos pueden ser convertidos a un carácter similar en el "encoding" final:
$txtFinal = iconv("UTF-8", "ISO-8859-1//TRANSLIT", $txtOriginal);

viernes, 12 de octubre de 2007

La pesadilla de los “encoding” (2ª parte)

Decíamos en la anterior entrada que cuando un fichero puede codificarse con UTF-8. Existen dos variantes del formato UTF-8: con BOM y sin BOM. BOM son dos bytes (FE FF) al principio de un fichero que, simplificando mucho, indican el orden de los bytes.
Guárdese un fichero codificado en UTF-8 con el BOM y tendrá problemas con la mayoría de sus scripts en PHP o ficheros XML, ya que el fichero realmente no comenzará como "<?php" o "<?xml".

Imaginen ahora el siguiente entorno de trabajo: un servidor web más o menos moderno que sirve los documentos por defecto con la codificación UTF-8, un desarrollador con una estación de trabajo Windows o Linux y un diseñador con la estación de trabajo Mac. Si el desarrollador y el diseñador no vigilan el "encoding" con el que guardan sus ficheros habrá problemas con seguridad. Muchas herramientas de desarrollo y/o diseño Web guardan por defecto los ficheros codificados con ISO-8859-1, otras lo guardan en UTF-8 con BOM.

Por supuesto, existen soluciones, a nivel servidor (ficheros .htaccess con la directiva AddDefaultCharset) y a nivel estación de trabajo utilizando herramientas competentes que puedan lidiar con las diferentes codificaciones.

Esta es la típica página que se ve mal porque el servidor sirve en ISO-8859-1 y el fichero está codificado como UTF-8:
Captura de un navegador mostrando caracteres UTF-8 como Latin-1

Se puede ver cómo los caracteres acentuados (ocupan 2 bytes en Unicode) son interpretados como 2 caracteres sencillos.

En el blog de Juque hay más ejemplos y se amplía más la información.

La conclusión final que obtengo es la siguiente: si no se puede garantizar una uniformidad en las plataformas de trabajo (que todo el mundo trabaje con el mismo "encoding"), lo más seguro es utilizar las entidades HTML de toda la vida (á en vez de á, ñ en vez de ñ, ...)

miércoles, 3 de octubre de 2007

La pesadilla de los “encoding”

Estamos en el año 2007. Internet forma parte de las vidas de muchas personas. Pues, por increíble que parezca, algun@s todavía tenemos que lidiar con problemas cuyo origen se remonta a varias décadas atrás.

Antecedentes: en los años 60 se aprobó un código estándard para la codificación de caracteres alfanuméricos. Era una buena idea, puesto que hasta el momento, cada fabricante usaba más o menos el código que le daba la gana. Con este código, ASCII, se consiguió una cierta estandarización.

La idea era utilizar 7 bits (lo que nos da 2^7 = 128 códigos diferentes) para representar los caracteres y símbolos del lenguaje escrito. Por ejemplo, el 65 (0100 0001 en binario) representaba la letra A (en mayúscula), el 32 (0010 0000 en binario) representaba el espacio en blanco, etc.

Magnífica ocurrencia, si tu idioma es inglés. En seguida l@s europe@s nos dimos cuenta de que este sistema no era muy válido: muchos caracteres no tenían representación: eñes, cedillas (ç), vocales con diversos acentos (á, à, â, ä, ...)

La solución que se encontró fue rápida: ya que un byte tiene 8 bits y el ASCII sólo utiliza 7 (el octavo bit se destinó para control de errores), se decidió utilizar ese octavo bit para ampliar el rango de caracteres disponibles (2^8 = 256). Surgía la codificación ISO-8859.

También parecía una buena idea, pero no resultó ser tan idónea: algunos idiomas necesitaban una ñ, por ejemplo, pero otros necesitaban una ç. Algunos idiomas europeos sólo necesitaban un tipo de acentos, pero otros utilizaban más. El resultado de estas necesidades diferentes fue que no se llegó a una única codificación utilizando 8 bits. La codificación ISO-8859-1 (también llamada Latin-1) sirve para casi todos los idiomas de Europa Occidental, la ISO-8859-15 es una revisión de ésta que incluye el símbolo del euro (€). La codificación ISO-8859-16 (Latin-2) se adapta a idiomas de Europa Oriental.

Por otra parte, otros fabricantes decidieron hacer lo que les pareció con el 8º bit no utilizado. Añadieron nuevos símbolos o caracteres extraños al ASCII estándar. Surgen así diversos "codepages" parcialmente compatibles entre ellos (CP437, Windows-1252, ...) y con ISO-8859

Estas codificaciones extendidas supusieron una mejora, pero no fueron el remedio definitivo. Además de mantenerse ciertas incompatibilidades, no servían para codificar algunos idiomas no alfabéticos (idiomas fonéticos o ideográficos).

La siguiente idea fue Unicode: utilizar 2 byte completos (o más) para representar los caracteres o símbolos. Con 2 bytes (2^16) ya tenemos 65.536 posibilidades o símbolos diferentes. Unicode consigue representar y asignar un código único a prácticamente cualquier símbolo escrito en cualquier idioma humano. Además, mantiene la compatibilidad con ASCII y Latin-1: los 128 primeros caracteres de Unicode se corresponden con la codificación ASCII, y los 128 siguientes (hasta 256) se corresponden con Latin-1.

El problema de Unicode es la transmisión de los datos: es absurdo reservar siempre dos bytes para un carácter cuando la mayor parte de los caracteres Unicode que se pueden transmitir en un momento dado "caben" en un byte. Las diferentes formas de transmitir e interpretar los caracteres Unicode son los famosos UTF, siendo los más utilizados UTF-8 y UTF-16.

Seguiremos con el tema.