¿Cómo internacionalizar una aplicación web Java?

81

Aprendí de Google que la internacionalización es el proceso mediante el cual puedo hacer que mi aplicación web use todos los idiomas. Quiero entender Unicode para el proceso de internacionalización, así que aprendí sobre Unicode aquí y allá .

Puedo entender acerca de Unicode que cómo un conjunto de caracteres se codifica en bytes y nuevamente los bytes se decodifican en conjunto de caracteres. Pero no sé cómo seguir adelante. Quiero aprender a comparar cadenas y necesito saber cómo implementar la internacionalización en mi aplicación web. ¿Alguna sugerencia por favor? Por favor guíame.

Mi objetivo:

Mi principal objetivo es desarrollar una aplicación web para traducción (del inglés al árabe y viceversa). Quiero seguir la internacionalización. Deseo ejecutar mi aplicación web para traducir en los tres navegadores, a saber, FF, Chrome, IE. ¿Cómo logro esto?

Yo soy Iron Man
fuente

Respuestas:

221

En el caso de una aplicación web JSP / Servlet básica, el enfoque básico sería utilizar JSTL fmttaglib en combinación con paquetes de recursos . Los paquetes de recursos contienen pares clave-valor donde la clave es una constante que es la misma para todos los idiomas y el valor varía según el idioma. Los paquetes de recursos suelen ser archivos de propiedades que se cargan mediante ResourceBundleAPI. Sin embargo, esto se puede personalizar para que pueda cargar los pares clave-valor desde, por ejemplo, una base de datos.

A continuación, se muestra un ejemplo de cómo internacionalizar el formulario de inicio de sesión de su aplicación web con paquetes de recursos basados ​​en archivos de propiedades.


  1. Cree los siguientes archivos y colóquelos en algún paquete, por ejemplo com.example.i18n(en el caso de Maven, colóquelos en la estructura del paquete src/main/resources).

    text.properties (contiene pares clave-valor en el idioma predeterminado, generalmente inglés)

     login.label.username = Nombre de usuario
     login.label.password = Contraseña
     login.button.submit = Iniciar sesión
     

    text_nl.properties(contiene nlpares clave-valor holandés ( ))

     login.label.username = Gebruikersnaam
     login.label.password = Wachtwoord
     login.button.submit = Inloggen
     

    text_es.properties(contiene espares clave-valor en español ( ))

     login.label.username = Nombre de usuario
     login.label.password = Contraseña
     login.button.submit = Acceder
     

    El nombre de archivo del paquete de recursos debe seguir el siguiente patrón name_ll_CC.properties. La _llparte debe ser el código de idioma ISO 693-1 en minúsculas . Es opcional y solo se requiere cuando la _CCpieza está presente. La _CCparte debe ser el código de país ISO 3166-1 Alpha-2 en mayúsculas . Es opcional y, a menudo, solo se usa para distinguir entre dialectos de idiomas específicos de un país, como el inglés americano ( _en_US) y el inglés británico ( _en_GB).


  2. Si aún no lo ha hecho, instale JSTL. Si está ejecutando en un contenedor Servlet 2.5 o más reciente (Tomcat 6.0 y así sucesivamente) y web.xmlse declara que cumple con la especificación Servlet 2.5, simplemente coloque jstl-1.2.jar en la /WEB-INF/libcarpeta de la aplicación web .


  3. Cree el siguiente archivo JSP de ejemplo y colóquelo en la carpeta de contenido web.

    login.jsp

     <%@ page pageEncoding="UTF-8" %>
     <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
     <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
     <c:set var="language" value="${not empty param.language ? param.language : not empty language ? language : pageContext.request.locale}" scope="session" />
     <fmt:setLocale value="${language}" />
     <fmt:setBundle basename="com.example.i18n.text" />
     <!DOCTYPE html>
     <html lang="${language}">
         <head>
             <title>JSP/JSTL i18n demo</title>
         </head>
         <body>
             <form>
                 <select id="language" name="language" onchange="submit()">
                     <option value="en" ${language == 'en' ? 'selected' : ''}>English</option>
                     <option value="nl" ${language == 'nl' ? 'selected' : ''}>Nederlands</option>
                     <option value="es" ${language == 'es' ? 'selected' : ''}>Español</option>
                 </select>
             </form>
             <form method="post">
                 <label for="username"><fmt:message key="login.label.username" />:</label>
                 <input type="text" id="username" name="username">
                 <br>
                 <label for="password"><fmt:message key="login.label.password" />:</label>
                 <input type="password" id="password" name="password">
                 <br>
                 <fmt:message key="login.button.submit" var="buttonValue" />
                 <input type="submit" name="submit" value="${buttonValue}">
             </form>
         </body>
     </html>
    

    El <c:set var="language">maneja el idioma actual. Si el idioma se proporcionó como parámetro de solicitud (mediante el menú desplegable de idiomas), se establecerá. De lo contrario, si el idioma ya se estableció previamente en la sesión, apéguese a él. De lo contrario, utilice la configuración regional proporcionada por el usuario en el encabezado de la solicitud.

    El <fmt:setLocale>establece la configuración regional para paquete de recursos. Es importante que esta línea esté antes del <fmt:setBundle>.

    El <fmt:setBundle>inicializa el paquete de recursos por su nombre de base (es decir, el nombre completo paquete calificado hasta con el único nombre sin el _ll_CCespecificador).

    Las <fmt:message>recupera el valor de la tecla de mensajes lote especificado.

    Los <html lang="${language}">informa al searchbots qué idioma se encuentra en la página de modo que no se marcará como contenido duplicado (por lo tanto, bueno para SEO).

    El menú desplegable de idiomas se enviará inmediatamente por JavaScript cuando se elija otro idioma y la página se actualizará con el idioma recién elegido.


Sin embargo, debe tener en cuenta que los archivos de propiedades se leen de forma predeterminada con la codificación de caracteres ISO-8859-1. Debería escapar de ellos mediante escapes Unicode. Esto se puede hacer utilizando la native2ascii.exeherramienta suministrada por JDK . Consulte también la sección de este artículo para obtener más detalles.

Una alternativa teórica sería proporcionar un paquete con una costumbre Controlpara cargar esos archivos como UTF-8, pero desafortunadamente no es compatible con el fmttaglib básico de JSTL . Debería gestionarlo todo usted mismo con la ayuda de a Filter. Hay marcos (MVC) que pueden manejar esto de una manera más transparente, como JSF, consulte también este artículo .

BalusC
fuente
2
Esta buena solución tiene un problema: la configuración regional tomada de la solicitud puede ser el idioma y el país, como en "en_US", lo que daría <html lang = "en_US">, que es HTML inválido. Es necesario utilizar solo la parte de idioma "en" de la configuración regional como valor para el atributo lang.
Torsten Römer
1
El método descrito anteriormente para la internacionalización no modifica la URL en función del idioma que se muestra. ¿Tiene alguna sugerencia sobre cómo actualizar la URL de acuerdo con el idioma? Lo pregunto porque, para la indexación, se recomienda que los diferentes idiomas tengan URL separadas: support.google.com/webmasters/answer/…
theyuv
1
Si coloca sus archivos de recursos de idioma (archivos de prueba.properties y text_en.properties) en la raíz de la aplicación / recursos, puede configurar el paquete fmt: de esta manera: <fmt: setBundle basename = "text" />
Bahadir Tasdemir
1
@bahadirT: asumiendo que "prueba" es un error tipográfico, eso es correcto. El basenamedebe representar el nombre de base sin extensión de archivo. No estructurarlo en un paquete es solo una mala práctica.
BalusC
1
@theyuv: User has {0} review{0,choice,0#s|1#|1<s} docs.oracle.com/javase/8/docs/api/java/text/MessageFormat.html
BalusC
26

Además de lo que dijo BalusC, debes tener cuidado con la direccionalidad (ya que el inglés se escribe de izquierda a derecha y el árabe al revés). La forma más sencilla sería agregar un diratributo al htmlelemento de su página web JSP y externalizarlo, de modo que el valor provenga del archivo de propiedades (al igual que con otros elementos o atributos):

<html dir="${direction}">
...
</html>

Además, hay algunos problemas con el estilo de dicha aplicación; por lo menos, debe evitar el posicionamiento absoluto. Si no puede evitar eso por alguna razón, puede usar diferentes hojas de estilo por (¿cada?) Idioma o hacer algo que esté prohibido , es decir, usar tablas para administrar el diseño. Si desea utilizar elementos div, le sugiero que utilice el posicionamiento relativo con atributos de estilo "simétricos" izquierdo y derecho (ambos con el mismo valor), ya que esto es lo que hace que el cambio de direccionalidad funcione.

Puede encontrar más información sobre los sitios web bidireccionales aquí .

Paweł Dyda
fuente
7
Sí, eso también hay que tenerlo en cuenta.
BalusC
4
<html dir="RTL">O <html dir="LTR">. El valor predeterminado es<html dir="LTR">
Fahim Parkar
2

Basado en este tutorial , estoy usando lo siguiente en GAE - App Engine de Google:

Un archivo jsp de la siguiente manera:

<%@ page import="java.io.* %>
<% 
  String lang = "fr"; //Assign the correct language either by page or user-selected or browser language etc.
  ResourceBundle RB = ResourceBundle.getBundle("app", new Locale(lang));
%>                 

<!DOCTYPE html>
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<head>
</head>
<body>
  <p>      
    <%= RB.getString("greeting") %>
  </p>
</body>

Y agregando los archivos llamados: app.properties(predeterminado) y app_fr.properties(y así sucesivamente para cada idioma). Cada uno de estos archivos debe contener las cadenas que necesita de la siguiente manera: key: value_in_language, por ejemplo, app_fr.propertiescontiene:

greeting=Bonjour!

app.properties contiene:

greeting=Hello!

Eso es todo

Ronen Rabinovici
fuente
10
¡Ugf, Scriptlets!
Nestor Hernandez Loli