Wie internationalisiere ich eine Java-Webanwendung?

81

Ich habe von Google erfahren, dass Internationalisierung der Prozess ist, mit dem ich meine Webanwendung so gestalten kann, dass alle Sprachen verwendet werden. Ich möchte Unicode für den Internationalisierungsprozess verstehen, deshalb habe ich von hier und da etwas über Unicode gelernt .

Ich kann über Unicode verstehen, wie ein Zeichensatz in Bytes codiert und wieder Bytes in Zeichensatz decodiert wird. Aber ich weiß nicht, wie ich weiter vorankommen soll. Ich möchte lernen, wie man Zeichenfolgen vergleicht, und ich muss wissen, wie man Internationalisierung in meiner Webanwendung implementiert. Irgendwelche Vorschläge bitte? Bitte führen Sie mich.

Mein Ziel:

Mein Hauptziel ist die Entwicklung einer Webanwendung für die Übersetzung (Englisch nach Arabisch und umgekehrt). Ich möchte der Internationalisierung folgen. Ich möchte meine Webanwendung für die Übersetzung in allen drei Browsern ausführen, nämlich FF, Chrome, IE. Wie erreiche ich das?

Ich bin Iron Man
quelle

Antworten:

220

Im Falle einer grundlegenden JSP / Servlet-Webanwendung würde der grundlegende Ansatz darin bestehen, JSTL- fmtTaglib in Kombination mit Ressourcenpaketen zu verwenden . Ressourcenpakete enthalten Schlüssel-Wert-Paare, wobei der Schlüssel eine Konstante ist, die für alle Sprachen gleich ist und der Wert je nach Sprache unterschiedlich ist. Ressourcenpakete sind normalerweise Eigenschaftendateien, die von der ResourceBundleAPI geladen werden . Dies kann jedoch so angepasst werden, dass Sie die Schlüssel-Wert-Paare beispielsweise aus einer Datenbank laden können.

Hier ist ein Beispiel für die Internationalisierung des Anmeldeformulars Ihrer Webanwendung mit auf Eigenschaftendateien basierenden Ressourcenpaketen.


  1. Erstellen Sie die folgenden Dateien und fügen Sie sie in ein Paket ein, z. B. com.example.i18n(im Fall von Maven fügen Sie sie in die darin enthaltene Paketstruktur ein src/main/resources).

    text.properties (enthält Schlüssel-Wert-Paare in der Standardsprache, normalerweise Englisch)

     login.label.username = Benutzername
     login.label.password = Passwort
     login.button.submit = Anmelden
     

    text_nl.properties(enthält niederländische ( nl) Schlüssel-Wert-Paare)

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

    text_es.properties(enthält spanische ( es) Schlüssel-Wert-Paare)

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

    Der Dateiname des Ressourcenpakets sollte dem folgenden Muster entsprechen name_ll_CC.properties. Der _llTeil sollte der ISO 693-1- Sprachcode in Kleinbuchstaben sein . Es ist optional und nur erforderlich, wenn das _CCTeil vorhanden ist. Das _CCTeil sollte der ISO 3166-1 Alpha-2- Ländercode in Großbuchstaben sein . Es ist optional und wird häufig nur zur Unterscheidung zwischen länderspezifischen Sprachdialekten wie amerikanischem Englisch ( _en_US) und britischem Englisch ( _en_GB) verwendet.


  2. Wenn noch nicht fertig, installieren Sie JSTL. Wenn Sie auf einem Servlet 2.5-Container oder einem neueren (Tomcat 6.0 usw.) ausgeführt werden und web.xmldie Servlet 2.5-Spezifikation als konform deklariert ist, legen Sie einfach jstl-1.2.jar im /WEB-INF/libOrdner der Webanwendung ab .


  3. Erstellen Sie die folgende Beispiel-JSP-Datei und legen Sie sie im Webinhaltsordner ab.

    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>

    Der <c:set var="language">verwaltet die aktuelle Sprache. Wenn die Sprache als Anforderungsparameter angegeben wurde (per Sprach-Dropdown), wird sie festgelegt. Andernfalls, wenn die Sprache bereits zuvor in der Sitzung festgelegt wurde, bleiben Sie stattdessen dabei. Verwenden Sie andernfalls das vom Benutzer angegebene Gebietsschema im Anforderungsheader.

    Das <fmt:setLocale>legt das Gebietsschema für das Ressourcenpaket fest. Es ist wichtig, dass diese Zeile vor dem steht <fmt:setBundle>.

    Das <fmt:setBundle>initialisiert das Ressourcenpaket anhand seines Basisnamens (dh des vollständig qualifizierten Paketnamens bis zum alleinigen Namen ohne den Bezeichner _ll_CC).

    Der <fmt:message>ruft den Nachrichtenwert mit dem angegebenen Bundle-Schlüssel ab.

    Das <html lang="${language}">informiert die Suchbots darüber, in welcher Sprache die Seite ist, damit sie nicht als doppelter Inhalt markiert wird (also gut für SEO).

    Das Sprach-Dropdown-Menü wird sofort per JavaScript gesendet, wenn eine andere Sprache ausgewählt wird, und die Seite wird mit der neu ausgewählten Sprache aktualisiert.


Beachten Sie jedoch, dass Eigenschaftendateien standardmäßig mit der ISO-8859-1-Zeichencodierung gelesen werden. Sie müssten ihnen durch Unicode-Escapezeichen entkommen. Dies kann mit dem von JDK bereitgestellten native2ascii.exeTool erfolgen. Siehe auch diesen Artikelabschnitt für weitere Details.

Eine theoretische Alternative wäre, ein Bundle mit einem benutzerdefinierten Befehl Controlzum Laden dieser Dateien als UTF-8 fmtbereitzustellen. Dies wird jedoch von der grundlegenden JSTL- Taglib leider nicht unterstützt . Sie müssten alles selbst mit Hilfe von a verwalten Filter. Es gibt (MVC) Frameworks, die dies transparenter handhaben können, wie JSF, siehe auch diesen Artikel .

BalusC
quelle
2
Diese nette Lösung hat ein Problem: Das aus der Anfrage entnommene Gebietsschema kann Sprache und Land sein, wie in "en_US", was <html lang = "en_US"> ergeben würde, was ungültiges HTML ist. Es ist erforderlich, nur den Sprachteil "en" aus dem Gebietsschema als Wert für das lang-Attribut zu verwenden.
Torsten Römer
1
Die oben für die Internationalisierung beschriebene Methode ändert die URL nicht basierend auf der angezeigten Sprache. Haben Sie Vorschläge, wie Sie die URL entsprechend der Sprache aktualisieren können? Ich frage, weil für die Indizierung empfohlen wird, dass verschiedene Sprachen separate URLs haben: support.google.com/webmasters/answer/…
Theyuv
1
Wenn Sie Ihre Sprachressourcendateien (test.properties und text_en.properties) im Anwendungs- / Ressourcenstamm ablegen, können Sie das Paket fmt: folgendermaßen festlegen: <fmt: setBundle basename = "text" />
Bahadir Tasdemir
1
@bahadirT: Angenommen, "Test" ist ein Tippfehler, das ist richtig. Das basenamemuss den Basisnamen ohne Dateierweiterung darstellen. Es ist nur eine schlechte Praxis, es nicht in einem Paket zu strukturieren.
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

Zusätzlich zu dem, was BalusC gesagt hat, muss man sich um die Direktionalität kümmern (da Englisch von links nach rechts und Arabisch umgekehrt geschrieben ist). Am einfachsten ist es, dirdem htmlElement Ihrer JSP-Webseite ein Attribut hinzuzufügen und es zu externalisieren, sodass der Wert aus der Eigenschaftendatei stammt (genau wie bei anderen Elementen oder Attributen):

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

Es gibt auch einige Probleme beim Styling einer solchen Anwendung - Sie sollten gelinde gesagt eine absolute Positionierung vermeiden. Wenn Sie dies aus irgendeinem Grund nicht vermeiden können, können Sie entweder verschiedene Stylesheets pro (jeder?) Sprache verwenden oder etwas tun, das verboten ist, dh Tabellen zum Verwalten des Layouts verwenden. Wenn Sie div-Elemente verwenden möchten, würde ich empfehlen, die relative Positionierung mit "symmetrischen" linken und rechten Stilattributen (beide mit demselben Wert) zu verwenden, da dies das Funktionieren der Richtungsumschaltung bewirkt.

Weitere Informationen zu bidirektionalen Websites finden Sie hier .

Paweł Dyda
quelle
7
Ja, das muss auch berücksichtigt werden.
BalusC
4
<html dir="RTL">ODER <html dir="LTR">. Standard ist<html dir="LTR">
Fahim Parkar
2

Basierend auf diesem Tutorial verwende ich Folgendes in GAE - Googles App Engine:

Eine JSP-Datei wie folgt:

<%@ 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>

Und Hinzufügen der Dateien mit dem Namen: app.properties(Standard) und app_fr.properties(und so weiter für jede Sprache). Jede dieser Dateien sollte die folgenden Zeichenfolgen enthalten: key: value_in_language, z. B. app_fr.propertiesenthält:

greeting=Bonjour!

app.properties enthält:

greeting=Hello!

Das ist alles

Ronen Rabinovici
quelle
9
Uggh, Scriptlets!
Nestor Hernandez Loli