Las grandes sites normalmente necesitan complacer a los visitantes de todo el mundo, y servir el contenido s�lo en un idioma no es suficiente. Para desarrollar una site que proporcione una elecci�n de idiomas, tenemos dos opciones:
- Escribir un conjunto de p�ginas para cada idioma.
- Escribir un conjunto compartido de p�ginas que ponga el contenido en diferentes idiomas desde fuentes externas.
Frecuentemente terminaremos con una mezcla de estas t�cnicas, usar p�ginas separadas para la mayor�a de las grandes cantidades de contenido est�tico y p�ginas compartidas cuando la cantidad de contenido sea peque�a pero din�mica (por ejemplo, una p�gina con unas pocas etiquetas fijas mostradas en diferentes idiomas y todos los dem�s datos que vengan desde una base de datos).
Preparar una aplicaci�n para varios idiomas se llama internacionalizaci�n (comunmente abreviado i18n) y hacer que el contenido est� disponible para un idioma espec�fico se llama localizaci�n (o l10n). Para hacer esto necesitamos considerar otras cosas adem�s del idioma. C�mo se formatean las fechas y n�meros entre los diferentes pa�ses, e incluso dentro de los pa�ses. Tambi�n podr�amos necesitar adaptar los colores, las im�genes y otro contenido no textual. El t�rmino localidad se refiere a un conjunto de reglas y contenido aceptable para una regi�n o cultura.
�Formateo de Fechas y N�meros Sensible a la Localidad
JSTL incluye un conjunto de acciones para simplificar la internacionalizaci�n, principalmente cuando p�ginas compartidas se usan para varios idiomas. Primero veamos c�mo formatear apropiadamente fechas y n�meros. Este ejemplo formatea la fecha actual y un n�mero bas�ndose en las reglas de la localidad por defecto:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %> <html> <body> <h1>Formatting with the default locale</h1> <jsp:useBean id="now" class="java.util.Date" /> Date: <fmt:formatDate value="${now}" dateStyle="full" /> Number: <fmt:formatNumber value="${now.time}" /> </body> </html>
La primera l�nea es la directiva taglib para la librer�a JSTL que contiene las acciones de formateo e internacionalizaci�n. El prefijo por defecto, usado aqu�, es fmt. Para obtener un valor a formatear, entonces crea un objeto java.util.Date que representa la fecha y hora actuales, y lo graba como una variable llamada now.
Ya estamos preparados para hacer alg�n formateo sensible a la localidad. La acci�n JSTL <fmt:formatDate> formatea el valor de la variable now asignado al valor del atributo value usando el tipo de expresi�n EL que aprendimos en la p�gina anterior. El atributo dateStyle le dice a la acci�n c�mo debe formatear la fecha.
Podemos usar cualquiera de los valores default, short, medium, long, o full para el atributo dateStyle. El tipo de formateo que representa cada uno de estos tipos depende exactamente de la localidad. Para la localidad English, full resulta en un string como Thursday, August 29, 2002. En este ejemplo, s�lo hemos formateado la parte de la fecha, pero tambi�n podemos incluir la parte de la hora (o formatear s�lo la hora), y definir reglas de formateo personalizadas tanto para la fecha como para la hora en lugar de los estilos dependientes de la localidad:
<fmt:formatDate value="${now}" type="both" pattern="EEEE, dd MMMM yyyy, HH:mm" />
El atributo pattern toma un patr�n de formateo personalizado del mismo tipo que la clase java.text.SimpleDateFormat. El patr�n usado aqu� resulta en Thursday, 29 August 2002, 17:29 con la localidad English. La acci�n <fmt:formatNumber> soporta atributos similares para especificar c�mo formatear un n�mero usando estilos dependientes de la localidad para n�meros normales, valores de moneda, o un porcentaje, as� como usar patrones personalizados de diferentes tipos.
�Usar JSTL para Seleccionar la Localidad
Volviendo a la cuesti�n principal: �C�mo se determina la localidad para formatear las fechas y los n�meros? Si usamos las acciones JSTL exactamente como en este ejemplo, sin hacer nada m�s, el formateo de localidad se determina comparando las localidades especificadas en un cabecera de solicitud llamada Accept-Language con las localidades soportadas por el entorno de ejecuci�n Java.
La cabecera, si est� presente, contiene una o m�s especificaciones de localidades (en la forma de c�digo de idioma y posiblemente un c�digo de pa�s), con informaci�n sobre su prioridad relativa. El usuario utiliza las configuracioens del navegador para definir qu� especificaciones de localidades enviar. Las localidades de la solicitud se comparan en orden de prioridad con las ofrecidas por la m�quina virtual Java, y se selecciona la que mejor coincida.
Si no se encuentra una correspondencia, la acci�n de formateo busca la llamada selecci�n de configuraci�n de la localidad pre-definida. Una selecci�n de configuraci�n es un valor seleccionado por un par�metro de contexto en el fichero web.xml de la aplicaci�n o por una acci�n JSTL o una sentencia Java en uno de los �mbitos JSP. Para seleccionar esta localidad en el fichero web.xml, incluimos estos elementos:
<context-param> <param-name> javax.servlet.jsp.jstl.fmt.fallbackLocale </param-name> <param-value> de </param-value> </context-param>
Con esta selecci�n, se usar� la localidad German (especificada por el c�digo de idioma de como valor de par�metro) si ninguna de las localidades especificadas por la solicitud est� soportada por el entorno Java.
JSTL tambi�n nos permite seleccionar una localidad por defecto para la aplicaci�n que podremos sobreescribir cuando lo necesitemos. Esto nos da control total sobre la localidad a utilizar, en lugar de dejarlo a la configuraci�n del navegador del visitante. La localidad por defecto tambi�n es una selecci�n de configuraci�n. Se puede especificar con un par�metro de contexto en el fichero web.xml de esta forma:
<context-param> <param-name> javax.servlet.jsp.jstl.fmt.locale </param-name> <param-value> en </param-value> </context-param>
Esta selecci�n establece English como la localidad por defecto, resultando en la anterior p�gina JSP siempre formatear� la fecha y los n�meros de acuerdo a las reglas inglesas.
Para sobreescribir la configuraci�n del localidad por defecto, podemos usar la acci�n <fmt:setLocale>. Selecciona la localidad por defeco dentro de un �mbito JSP espec�fico. Aqu� tenemos un ejemplo que selecciona la localidad por defecto del �mbito de la p�gina, bas�ndose en una cookie que sigue la pista de la localidad seleccionada por el usuario en una visita anterior:
<h1>Formatting with a locale set by setLocale</h1> <c:if test="${!empty cookie.preferredLocale}"> <fmt:setLocale value="${cookie.preferredLocale.value}" /> </c:if> <jsp:useBean id="now" class="java.util.Date" /> Date: <fmt:formatDate value="${now}" dateStyle="full" /> Number: <fmt:formatNumber value="${now.time}" />
Aqu�, primero hemos usado la acci�n JSTL <c:if> para comprobar si con la solicitud se ha recibido una cookie llamada preferredLocale. Si es as�, la acci�n <fmt:setLocale> sobreescribe la localidad para la p�gina actual seleccionan la variable de configuraci�n de la localidad en el �mbito de la p�gina. Si lo queremos, podemos seleccionar la localidad para otro �mbito usando el atributo scope. Finalmente, se formatean la fecha y el n�mero de acuerdo a las reglas de la localidad especificada por la cookie, o la localidad por defecto, si la cookie no est� presente.
Adem�s de acciones para formateo, JSTL incluye acciones para interpretar (analizar) fechas y n�mero de una forma sensible a la localidad: <fmt:parseDate> y <fmt:parseNumber>. Estas acciones soportan casi todos los mismos atributos que sus contrapartidas de formateo, y se pueden utilizar para convertir entradas de fechas y n�meros en sus formas nativas antes de procesarlas.
�Usar un Controlador para Selecciona la Localidad
Si has desarrollado aplicaciones Web usando tecnolog�a Java, sin duda habr�s o�do algo sobre el patr�n MVC y mejor, sobre el marco de trabajo Struts de Apache. La idea b�sica que hay detr�s del patr�n MVC es que una aplicaci�n es m�s f�cil de mantener y evolucionar si las diferentes partes de la aplicacion (Modelo, Vista y Controlador) se implementan como componentes separados. Para Java, esto normalmente significa usar Beans como el Modelo (l�gica de negocio), p�ginas JSP para la Vista (el interface de usuario) y un servlet como el Controlador (la parte que controla la comunicaci�n entre la Vista y el Modelo). Struts proporciona un servlet Controlador gen�rico que delega el procesamiento espec�fico de tipos espec�ficos de solicitudes a classes llamadas clases Action, y luego usa una p�gina JSP especificada por la Action para generar la respuesta.
JSTL est� dise�ado para jugar bien en una aplicaci�n basada en MVC exponiendo una clase que puede ser utilizada por cualquier componente Java, como una clase Action de Struts, para acceder a las variables de configuraci�n usadas por las acciones JSTL en las p�ginas JSP que representan la Vista. La clase se llama javax.servlet.jsp.jstl.core.Config y contiene constantes ( variables static final String) para todas las variables de configuraci�n, y m�todos para seleccionar, obtener y eliminar las variables en diferentes �mbitos JSP. Podemos usar c�digo como este en una clase Action de Struts para seleccionar la localidad por defecto para la sessi�n, basado en un p�rfil de datos, cuando un usuario entra en la aplicaci�n:
import javax.servlet.jsp.jstl.core.Config; ... public class LoginAction extends Action { public ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String userName = request.getParameter("userName"); String password = request.getParameter("password"); ... User user = authenticate(userName, password); if (user != null) { /* * Valid user. Set the default locale in the session * to the user's preferred locale */ HttpSession session = request.getSession(); Config.set(session, Config.FMT_LOCALE, user.getLocale()); ... } } }
La clase Config proporciona cuatro m�todos set(), uno por cada �mbito JSP (especificado por el primer par�metro de m�todo). Aqu� hemos usado el que selecciona la variable en el �mbito de sesi�n. El segundo par�metro es el nombre de la configuraci�n, t�picamente seleccionado por la constante correspondiente. El tercer par�metro es el valor de la variable. Para leer y eliminar variable, la clase proporciona m�todos get() y remove() similares, m�s un m�todo find() para localizar una variable en cualquier �mbito. Adem�s de usar estos m�todos en un Controlador, podr�amos querer usarlos en nuestro propios manejadores de etiquetas personalizados para aprovecharnos de los mecanismos de configuraci�n JSTL.
�Generar Texto Localizado
Aunque formatear fechas y n�mero es importante cuando se localiza una aplicaci�n, el cotenido de texto es, por supuesto, incluso m�s importante. JSTL est� basado en Java, por eso trata con el soporte gen�rico de i18n de la plataforma Java. Cuando viene con texto, este soporte est� basado en lo que se llama un paquete de recursos. En su forma m�s simple, un paquete de recursos est� representado por un fichero de texto que contiene claves y un valor de texto para cada clave. Este ejemplo muestra un fichero con dos claves (hello y goodbye) y sus valores:
hello=Hello goodbye=Goodbye
Las distintas localidades se soportan creando ficheros separados para cada una de ellas, con un nombre de fichero que incluye el nombre de la localidad. Por ejemplo, si el fichero del paquete de recursos anterior representa la localidad English, deber�a almacenarse en un fichero llamado labels_en.properties. El paquete de recursos para la localidad Swedish ser�a almacenado en un fichero llamado labels_sv.properties, donde sv es el c�digo de idioma. La parte fija del nombre de fichero, labels de este ejemplo, se llama el nombre base del paquete de recursos, y se combina con una especificaci�n de localidad (como un c�digo de idioma) para encontrar el paquete de recursos para una localidad espec�fica. Todos los paquetes de recursos incluyen las mismas claves; s�lo difiere el texto dependiendo de la localidad. Los ficheros deben situarse en un directorio que sea parte del classpath del contenedor, normalmente el directorio WEB-INF/classes de la aplicaci�n.
La acci�n JSTL que a�ade texto desde un paquete de recursos a una p�gina es <fmt:message>. El paquete a utilizar puede especificarse de varias formas. Una es anidar las acciones <fmt:message> dentro del cuerpo de una acci�n <fmt:bundle>:
<fmt:bundle basename="labels"> Hello: <fmt:message key="hello" /> Goodbye: <fmt:message key="goodbye" /> </fmt:bundle>
En este caso, la acci�n <fmt:bundle> localiza el paquete de la localidad que es la correspondencia m�s cercana entre la selecci�n de configuraci�n de la localidad (o las localidades en el cabecera Accept-Language, si no hay localidad por defecto) y los paquetes de recursos disponibles para el nombre base especificado. Las acciones anidadas obtienen el texto desde el paquete por la clave asociada.
Al igual que con las acciones de formateo, podemos establecer un paquete por defecto, para toda la aplicaci�n con un par�metro de contexto o con la acci�n <fmt:setBundle> o la clase Config para un �mbito JSP espec�fico:
<fmt:setBundle basename="labels"/> ... Hello: <fmt:message key="hello" /> Goodbye: <fmt:message key="goodbye" />
Despu�s de que se haya definido un paquete por defecto, podemos usar acciones <fmt:message> independientes dentro del �mbito donde se estableci� el valor por defecto.