Programación en castellano
Inicio > Tutoriales > Lenguajes orientados a objeto > J2SE > Internacionalización de Programas Java
-Tutoriales

Internacionalización de Programas Java


Detectar Límites de Texto

Las aplicaciones que manipulan texto necesitan localizar límites dentro del propio texto. Por ejemplo, consideremos algunas de las funciones comunes en un procesador de textos: iluminar un caracter, cortar una palabra, mover el cursor al párrafo siguiente, y cortar las palabras al final de la línea. Para realizar cada una de estas funciones, el procesador de textos debe poder detectar los límites lógicos del texto. Afortunadamente, no tenemos que escribir nuestras propias rutinas para realizar análisis de límites. En su lugar, podemos aprovecharnos de los métodos propocionados por la clase BreakIterator.

. Sobre la clase BreakIterator

Esta sección explica la ejemplarización de métodos y los cursores imaginarios de la clase BreakIterator.

clase BreakIterator es sensible a la Localidad, porque los límites de texto pueden variar con el idioma. Por ejemplo, la reglas para ruptura de líneas no son las mismas para todos los idiomas. Para determinar las Localidades soportadas por la clase BreakIterator se llama al método getAvailableLocales.

Locale[] locales = BreakIterator.getAvailableLocales();

Se pueden analizar cuatro tipos diferentes de límites con la clase BreakIterator: caracter, palabra, párrafo y ruptura potencial de línea. Cuande se ejemplariza un BreakIterator, se debe llamar al método de creacción apropiado.

  • getCharacterInstance
  • getWordInstance
  • getSentenceInstance
  • getLineInstance

Cada ejemplar de BreakIterator sólo puede detectar un tipo de límite. Si se quiere localizar el límite de caracter y de palabra, por ejemplo, se necesitará crear dos ejemplares separados.

Un BreakIterator tiene un cursor imaginario que apunta al límite actual en una cadena de texto. Se puede mover este cursor dentro del texto con los métodos previous y next. Por ejemplo, si hemos creado un BreakIterator con getWordInstance, cada vez que llamemos al método next el cursor de moverá al siguiente límite de palabra dentro del texto. Los métodos de movimiento del cursor devuelven un entero indicando la posición del límite. Esta posición es el índice del caracter de la cadena de texto que sigue al límite. Al igual que los Strings indexados, los límites están basados en cero. El primer límite es el 0, y el último límite es la longitud de la cadena.

Se debería utilizar la clase BreakIterator sólo con texto natural. No se debe utilizar con lenguajes de programación.

En las siguientes secciones, proporcionaremos ejemplos de cada tipo de límite. Los ejemplos de código se han extraido de un fichero llamado BreakIteratorDemo.java.

. Límite de Caracter

En esta sección aprenderás la diferencia entre los caracteres de usuario y los caracteres Unicode, y como localizar los caracteres de usuario con un BreakIterator.

necesitará localizar los límites de caracter si nuestra aplicación permite al usuario final seleccionar caracteres individuales. o mover el cursor a través del texto caracter a caracter. Para crear un BreakIterator que localice los límites de caracter se llama al método getCharacterInstance.

BreakIterator characterIterator = 
   BreakIterator.getCharacterInstance(currentLocale);

Este tipo de BreakIterator detecta límites entre caracteres de usuario, no sólo caracteres Unicode. Los caracteres de usuario varían con el idioma, pero la clase BreakIterator puede reconocer estas diferencias porque es sensible a la Localidad. Un caracter de usuario podría estar compuesto por uno o más caracteres Unicode. Por ejemplo, el caracter de usuario ü podría componerse combinando los caracteres Unicode '\u0075' (u) '\u00a8' (¨). Sin embargo, este no es el mejor ejemplo, porque el caracter ü también podría ser represetnado por un sólo caracter Unicode '\u00fc'. Veremos el idioma Árabe para un ejemplo más realista.

En Árabe, la palabra para casa es.

Aunque esta palabra contiene tres caracteres de usuario, está compuesta por seis caracteres Unicode.

String house = "\u0628" + "\u064e" + "\u064a" + 
               "\u0652" + "\u067a" + "\u064f";

Los caracteres Unicode de las posiciones 1,3 y 5 en la cadena house son diacríticos. En Árabe los diacríticos son necesarios, porque pueden alterar el significado de las palabras. Los diacríticos en nuesto ejemplo son caracteres no blancos ya que aparecen sobre los caracteres base. En un procesador de textos árabe, no podemos mover el cursor sobre cada caracter Unicode de la cadena. En su lugar, debemos movernos sobre cada caracter de usuario, que podría estar compuesto por más de un caracter Unicode. Por lo tanto, debemos utilizar un BreakIterator para scanear los caracteres de usuario en la cadena.

En nuestro ejemplo, BreakIteratorDemo.java, hemos creado un BreakIterator para scanear caracteres arábicos. Luego pasamos este BreakIterator, junto con el objeto String creado anteriormente, al método llamado listPositions.

BreakIterator arCharIterator =
   BreakIterator.getCharacterInstance(new Locale ("ar","SA"));

listPositions (house,arCharIterator);

El método listPositions utiliza un BreakIterator para localizar los límites de caracter dentro de la cadena. Observa que asignamos un string particular al BreakIterator con el método setText. Recuperamos el primer límite de caracter con el método first, luego llamamos al método next hasta que se devuelva la constante BreakIterator.DONE. Aquí podemos ver el código de esta rutina.

static void listPositions(String target, BreakIterator iterator) {

   iterator.setText(target);
   int boundary = iterator.first();

   while (boundary != BreakIterator.DONE) {
      System.out.println (boundary);
      boundary = iterator.next();
   }
}

El método listPositions imprime las siguientes posiciones de límites para los caracteres de usuario de la cadena house. Las posiciones de los diacríticos (1, 3, 5) no se listan.

0
2
4
6

. Límite de Palabra

Si la aplicación necesita seleccionar o lacalizar palabras dentro del texto, encontraremos util el uso de un BreakIterator.

invoca al método getWordIterator para ejemplarizar un BreakIterator que detecte límites de palabra.

BreakIterator wordIterator =
   BreakIterator.getWordInstance(currentLocale);

Querremos crear un BreakIterator como éste cuando nuestras aplicaciones necesiten realizar operaciones con palabras individuales. Estas operaciones podrían ser las funciones comunes de los procesadores de textos como selecionar, cortar, pegar y copiar. O nuestras aplicaciones podrían buscar palabras, y para hacer esto necesitan poder distinguir entre palabras completas.

Cuando se realizan análisis de límites de palabra, un BreakIterator diferencia entre las palabras y los caracteres que no forman parte de las palabras. Estos caracteres, que incluyen espacios, tabuladores, marcas de puntuación, y algunos símbolos, tienen límites de palabras en ámbos lados.

En el siguiente ejemplo, extraido del programa BreakIteratorDemo.java, queremos marcar los límites de palabras en algún texto. Primero creamos el BreakIterator y luego llamamos a un método que hemos escrito llamado markBoundaries.

Locale currentLocale = new Locale ("en","US");

BreakIterator wordIterator =
   BreakIterator.getWordInstance(currentLocale);

String someText = "She stopped.  " +
                  "She said, \"Hello there,\" and then went on.";

markBoundaries(someText, wordIterator);

El propósito de este método es marcar los límites de palabras en un string con un caracter ('^'). Cada vez que BreakIterator detecta un límite palabra, insertamos este caracter en el buffer markers. Scaneamos el string en un bucle, llamando al método next hasta que devuelva BreakIterator.DONE. Aquí tenemos el código de la rutina markBoundaries.


static void markBoundaries(String target, BreakIterator iterator) {

   StringBuffer markers = new StringBuffer();
   markers.setLength(target.length() + 1);
   for (int k = 0; k < markers.length(); k++) {
      markers.setCharAt(k,' ');
   }

   iterator.setText(target);
   int boundary = iterator.first();

   while (boundary != BreakIterator.DONE) {
      markers.setCharAt(boundary,'^');
      boundary = iterator.next();
   }

   System.out.println(target);
   System.out.println(markers);
} 

El método markBoundaries imprime el string target y el buffer markers. Obseva donde ocurren los caracteres ('^') en relación con las marcas de puntuación y los espacios.

She stopped.  She said, "Hello there," and then went on.
^  ^^      ^^ ^  ^^   ^^^^    ^^    ^^^^  ^^   ^^   ^^  ^

El BreakIterator hace sencilla la selección de palabras dentro de un texto. No tenemos que escribir nuestras propias rutinas para manejar las reglas de puntuación de los distintos idiomas, porque la clase BreakIterator lo hace por nosotros. Aquí podemos ver una subrutina que extrae e imprime las palabras de una cadena dada.

static void extractWords(String target, BreakIterator wordIterator) {

   wordIterator.setText(target);
   int start = wordIterator.first();
   int end = wordIterator.next();

   while (end != BreakIterator.DONE) {
      String word = target.substring(start,end);
      if (Character.isLetterOrDigit(word.charAt(0))) {
         System.out.println(word);
      }
      start = end;
      end = wordIterator.next();
   }
} 

En nuestro ejemplo, llamamos a extractWords, le pasamos la misma cadena que en el ejemplo anterior. El método extractWords imprimirá la siguiente lista de palabras.

She
stopped
She
said
Hello
there
and
then
went
on.

. Límites de Párrafo

Determinar los límites de párrafo puede ser problemático, debido a la utilización ambigua de terminadores de sentecias en muchos idiomas escritos. Esta sección examina algunos de los problemas que podremos encontrarnos, y como tratarlos con la clase BreakIterator.

En muchos idiomas el terminador de sentencia es un punto. En Inglés, también se utiliza un punto para especificar el separador decimal, para indicar una marca de elipsis, y para terminar abreviaturas. Cómo el punto tiene más de un propósito, no podemos determinar el límite se sentencia con total seguridad.

Primero, echemos un vistazo a un caso en el que si funciona la detección de límite de sentencia. Empezaremos creando un BreakIterator con el método getSentenceInstance.

BreakIterator sentenceIterator =
   BreakIterator.getSentenceInstance(currentLocale);

Para demostrar los límites de sentencias, utilizaremos el método markBoundaries, que se explicó en la sección anterior. El método markBoundaries imprime caracteres ('^') en un string para indicar las posiciones de los límites. En el siguiente ejemplo, los límites de sentencias están definidos apropiadamente.

She stopped.  She said, "Hello there," and then went on.
^             ^                                         ^

También se pueden localizar los límites de sentencias que terminen en interrogaciones o puntos de exaclamación.

He's vanished!  What will we do?  It's up to us.
^               ^                 ^             ^

Utilizar el punto como separador decimal no provoca ningún error.

Please add 1.5 liters to the tank.
^                                 ^

Una marca de elipsis (puntos suspensivos) indica la omisión de texto dentro de un pasaje entrecomillado. En el siguiente ejemplo los puntos suspensivos generan límites de sentencia.

"No man is an island . . . every man . . . "
^                      ^ ^             ^ ^ ^^

Las abreviaturas también podrían provocar errores. Si el punto es seguido por un espacio en blanco y una letra mayúscula, el BreakIterator detecta un límite de sentencia.

My friend, Mr. Jones, has a new dog.  The dog's name is Spot.
^              ^                      ^                      ^

. Límite de Línea

Esta sección describe como localizar las rupturas de línea potenciales en una cadena de texto con un BreakIterator.

Las aplicaciones que formatean texto o realizan ruptura de líneas deben localizar las rupturas de líneas potenciales. Se pueden encontrar estas rupturas de línea, o límites, con un BreakIterator que haya sido creado con el método getLineInstance.

BreakIterator lineIterator = 
   BreakIterator.getLineInstance(currentLocale);

Este BreakIterator determina la posición en que se puede romper una línea para continuar en la siguiente línea. Las posiciones detectadas por el BreakIterator son rupturas de líneas potenciales. La ruptura de línea real mostrada en la pantalla podría no ser la misma.

En los siguientes ejemplos, utilizamos el método markBoundaries para ver los límites de línea detectados por un BreakIterator. Este método imprime marcas en los límites de línea de la cadena fuente.

De acuerdo al BreakIterator, un límite de línea ocurre después del final de una secuencia de caracteres blancos, (space, tab, newline). En el siguiente ejemplo, podemos romper la línea en cualquiera de los límites detectados.

She stopped.  She said, "Hello there," and then went on.
^   ^         ^   ^     ^      ^       ^   ^    ^    ^  ^

Las rupturas de líneas potenciales también ocurren inmediatamente después de un guión.

There are twenty-four hours in a day.
^     ^   ^      ^    ^     ^  ^ ^   ^

En el siguiente ejemplo, rompemos una cadena en líneas de la misma longitud con un método llamado formatLines. Utilizamos un BreakIterator para localizar las rupturas de líneas potenciales. Para romper una línea, ejecutamos un System.out.println() siempre que la longitud de la línea actual alcance el valor del parámetro maxLength. El método formatLines es corto, sencillo, y gracias al BreakIterator, independiente de la Localidad. Aquí puedes ver su código fuente.


static void formatLines(String target, int maxLength, 
                        Locale currentLocale) {

   BreakIterator boundary = BreakIterator.getLineInstance(currentLocale);
   boundary.setText(target);
   int start = boundary.first();
   int end = boundary.next();
   int lineLength = 0;

   while (end != BreakIterator.DONE) {
      String word = target.substring(start,end);
      lineLength = lineLength + word.length();
      if (lineLength >= maxLength) {
         System.out.println();
         lineLength = word.length();
      }
      System.out.print(word);
      start = end;
      end = boundary.next();
   }
} 

En el programa BreakIteratorDemo.java llamamos a formatLines de esta forma.

String moreText = "She said, \"Hello there,\" and then " +
                  "went on down the street.  When she stopped " +
                  "to look at the fur coats in a shop window, " +
                  "her dog growled.  \"Sorry Jake,\" she said. " +
                  " \"I didn't know you would take it personally.\"";

formatLines(moreText, 30, currentLocale);

Aquí podemos ver la salida de la llamada a formatLines.

She said, "Hello there," and 
then went on down the 
street.  When she stopped to 
look at the fur coats in a 
shop window, her dog 
growled.  "Sorry Jake," she 
said.  "I didn't know you 
would take it personally."
 
Patrocinados
 

Copyright © 1999-2007 Programación en castellano. Todos los derechos reservados.
Formulario de Contacto - Datos legales - Publicidad
Mantenida por: Claudio y Dani.

Hospedaje web y servidores dedicados linux por Ferca Network

red internet: jugar gratis | amor | navidad 2009 | registro de dominios | servidores dedicados
más internet: comprar | gratis | posicionamiento en buscadores | decoración libre | gifs animados