Intl.Segmenter API: cómo dividir texto correctamente en JavaScript


A simple vista, dividir un texto en JavaScript parece trivial.

Tienes split(), separas por espacios y listo, ¿no?

"Según la  IA, esto estaba resuelto hace 3.00hs. Según producción, no.".split(" ");
// ["Según", "la", "", "IA,", "esto", "estaba",  "resuelto.", "hace", "3.00hs.", "Según", "producción,", "no."]

Y aquí ya empiezan los problemas.

Por suerte, existe una API nativa del navegador para esto: Intl.Segmenter.

Qué es Intl.Segmenter

Intl.Segmenter permite dividir texto de forma inteligente en:

Y aquí está la gracia: lo hace teniendo en cuenta el idioma y las reglas reales de segmentación.

Separar frases

Imagina este texto:

const text = "Según la IA, esto estaba resuelto. Según producción, no.";

Si quieres separar frases, puedes crear un segmentador así:

const segmenter = new Intl.Segmenter("en", {
  granularity: "sentence",
});

const segments = segmenter.segment(text);

El resultado no es un array directamente, sino un iterador. Si lo conviertes a array, verás que cada elemento contiene bastante información:

const segmentArray = Array.from(segments);
[
  {
    segment: "Según la IA, esto estaba resuelto. ",
    index: 0,
    input: "Según la IA, esto estaba resuelto. Según producción, no."
  },
  {
    segment: "Según producción, no.",
    index: 36,
    input: "Según la IA, esto estaba resuelto. Según producción, no."
  }
]

Si solo quieres el texto segmentado, lo normal es mapearlo:

const text = "Según la IA, esto estaba resuelto. Según producción, no.";

const segmenter = new Intl.Segmenter("en", {
  granularity: "sentence",
});

const segments = Array.from(segmenter.segment(text)).map(
  (segment) => segment.segment
);

console.log(segments);
[
  "Según la IA, esto estaba resuelto. ",
  "Según producción, no."
]

Separar palabras

También puedes segmentar por palabras:

const text = "Según la IA, esto estaba resuelto. Según producción, no.";

const segmenter = new Intl.Segmenter("en", {
  granularity: "word",
});

const segments = Array.from(segmenter.segment(text)).map(
  (segment) => segment.segment
);

console.log(segments);
[
  "Según",
  " ",
  "la",
  " ",
  "IA",
  ",",
  " ",
  "esto",
  " ",
  "estaba",
  " ",
  "resuelto",
  ".",
  " ",
  "Según",
  " ",
  "producción",
  ",",
  " ",
  "no",
  "."
]

Aquí pasa algo curioso: el resultado incluye espacios y signos de puntuación.

Eso puede parecer raro al principio, pero en realidad tiene sentido. La API no intenta adivinar qué quieres filtrar, solo te da una segmentación correcta.

Filtrar solo palabras reales

La buena noticia es que cada segmento incluye una propiedad llamada isWordLike.

Eso te permite quedarte solo con las palabras “de verdad”:

const text = "Según la IA, esto estaba resuelto. Según producción, no.";

const segmenter = new Intl.Segmenter("en", {
  granularity: "word",
});

const words = Array.from(segmenter.segment(text))
  .filter((segment) => segment.isWordLike)
  .map((segment) => segment.segment);

console.log(words);
[
  "Según",
  "la",
  "IA",
  "esto",
  "estaba",
  "resuelto",
  "Según",
  "producción",
  "no"
]

Esto ya es bastante más útil para cosas como:

Lo interesante de verdad: el Intl

La parte más potente de esta API no es solo que segmente texto, sino que lo hace respetando el idioma.

Y eso importa mucho más de lo que parece.

Por ejemplo, con japonés:

const text = "私の猫の名前はベティです。彼女はとてもかわいいです!";

const segmenter = new Intl.Segmenter("ja", {
  granularity: "sentence",
});

const segments = Array.from(segmenter.segment(text)).map(
  (segment) => segment.segment
);

console.log(segments);
[
  "私の猫の名前はベティです。",
  "彼女はとてもかわいいです!"
]

Aquí split() no te salva. Intl.Segmenter, sí.

También sirve para emojis

Hay una tercera granularidad: "grapheme".

Esto es útil cuando quieres dividir caracteres visuales reales, no unidades Unicode sueltas.

Un ejemplo clásico son los emojis:

"⛔⛈️🙂😵💫".split("");
// ["⛔", "⛈", "️", "\ud83d", "\ude42", "\ud83d", "\ude35", "\ud83d", "\udcab"]

Ese resultado no es lo que esperas.

Con Intl.Segmenter la cosa cambia:

const text = "⛔⛈️🙂😵💫";

const segmenter = new Intl.Segmenter("es", {
  granularity: "grapheme",
});

const segments = Array.from(segmenter.segment(text)).map(
  (segment) => segment.segment
);

console.log(segments);
["⛔", "⛈️", "🙂", "😵", "💫"]

Mucho mejor.

Cuándo tiene sentido usar esta API

Intl.Segmenter no es una API que vayas a usar en todos los proyectos, pero cuando la necesitas, marca bastante diferencia.

Encaja muy bien en casos como estos:

Si solo quieres partir una cadena súper simple y controlada, split() sigue siendo suficiente.

Pero si quieres hacerlo bien de verdad, Intl.Segmenter es una opción mucho más robusta.

Conclusión

Muchas veces intentamos resolver problemas de texto con split() porque parece lo más fácil.

Y a veces vale.

Pero en cuanto hay puntuación, espacios extra, varios idiomas o emojis, la realidad se pone juguetona.

Ahí es donde Intl.Segmenter brilla.

Es una de esas APIs nativas que no se mencionan tanto, pero que cuando la descubres piensas: vale, esto debería haberlo conocido antes.


Comparte