Jak umiędzynarodowić aplikację internetową Java?

81

Dowiedziałem się od Google, że internacjonalizacja to proces, dzięki któremu mogę dostosować moją aplikację internetową do obsługi wszystkich języków. Chcę zrozumieć Unicode dla procesu internacjonalizacji, więc dowiedziałem się o Unicode z tu i tam .

Jestem w stanie zrozumieć, że Unicode, w jaki sposób zestaw znaków jest zakodowany do bajtów i ponownie bajty zdekodowany do zestawu znaków. Ale nie wiem, jak pójść dalej. Chcę się dowiedzieć, jak porównywać ciągi znaków i wiedzieć, jak wdrożyć internacjonalizację w mojej aplikacji internetowej. Jakieś sugestie? Proszę, prowadź mnie.

Mój cel:

Moim głównym celem jest stworzenie aplikacji internetowej do tłumaczenia (z angielskiego na arabski i odwrotnie). Chcę podążać za internacjonalizacją. Chcę uruchamiać moją aplikację internetową do tłumaczenia we wszystkich trzech przeglądarkach, a mianowicie FF, Chrome, IE. Jak to osiągnąć?

Jestem Iron Man
źródło

Odpowiedzi:

221

W przypadku podstawowej aplikacji sieciowej JSP / Servlet, podstawowym podejściem byłoby użycie biblioteki fmttaglib JSTL w połączeniu z pakunkami zasobów . Pakiety zasobów zawierają pary klucz-wartość, w których klucz jest stałą, która jest taka sama dla wszystkich języków, a wartość różni się w zależności od języka. Pakiety zasobów są zwykle plikami właściwości ładowanymi przez ResourceBundleinterfejs API. Można to jednak dostosować, aby można było załadować pary klucz-wartość na przykład z bazy danych.

Oto przykład, jak umiędzynarodowić formularz logowania do aplikacji internetowej za pomocą pakietów zasobów opartych na plikach właściwości.


  1. Utwórz następujące pliki i umieść je w jakimś pakiecie, np. com.example.i18n(W przypadku Mavena, umieść je w strukturze pakietu w środku src/main/resources).

    text.properties (zawiera pary klucz-wartość w domyślnym języku, zwykle angielskim)

     login.label.username = nazwa użytkownika
     login.label.password = Hasło
     login.button.submit = Zaloguj się
     

    text_nl.properties(zawiera nlpary klucz-wartość w języku holenderskim ( ))

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

    text_es.properties(zawiera espary klucz-wartość w języku hiszpańskim ( ))

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

    Nazwa pliku pakietu zasobów powinna być zgodna z następującym wzorcem name_ll_CC.properties. _llCzęść powinna być małe litery ISO 693-1 kod języka. Jest to opcjonalne i wymagane tylko wtedy, gdy _CCczęść jest obecna. _CCCzęść powinna być wielka ISO 3166-1 alfa-2 kod kraju. Jest opcjonalny i często używany tylko do rozróżniania dialektów języka specyficznego dla danego kraju, takich jak amerykański angielski ( _en_US) i brytyjski angielski ( _en_GB).


  2. Jeśli jeszcze tego nie zrobiłeś, zainstaluj JSTL. Jeśli korzystasz z kontenera Servlet 2.5 lub nowszego (Tomcat 6.0 i tak dalej) i web.xmldeklarujesz zgodność ze specyfikacją Servlet 2.5, po prostu umieść jstl-1.2.jar w /WEB-INF/libfolderze webapp .


  3. Utwórz następujący przykładowy plik JSP i umieść go w folderze treści WWW.

    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>
    

    <c:set var="language">Zarządza bieżący język. Jeśli język został podany jako parametr żądania (z listy rozwijanej języka), zostanie ustawiony. W przeciwnym razie, jeśli język był już ustawiony w sesji, zamiast tego trzymaj się go. W przeciwnym razie użyj ustawień regionalnych podanych przez użytkownika w nagłówku żądania.

    <fmt:setLocale>Ustawia locale dla pakunku zasobów. To ważne, że ta linia jest przed<fmt:setBundle> .

    <fmt:setBundle>Inicjuje pakunek zasobów przez jego nazwy bazowej (czyli pełna kwalifikowana nazwa pakietu aż wyłącznie w imieniu bez _ll_CCspecyfikacją).

    W <fmt:message>Pobiera wartość wiadomość przez określonego klucza wiązki.

    Na <html lang="${language}">informuje searchbots co język strona jest w tak, że nie będą oznaczone jako duplikaty (co za tym idzie, dobre dla SEO).

    Menu rozwijane języka zostanie natychmiast przesłane przez JavaScript po wybraniu innego języka, a strona zostanie odświeżona w nowo wybranym języku.


Należy jednak pamiętać, że pliki właściwości są domyślnie odczytywane przy użyciu kodowania znaków ISO-8859-1. Musiałbyś uciec przed nimi przez ucieczki unicode. Można to zrobić za pomocą native2ascii.exenarzędzia dostarczonego przez JDK . Więcej szczegółów można znaleźć w tej sekcji artykułu .

Teoretyczną alternatywą byłoby dostarczenie pakietu z niestandardowym Controlładowaniem tych plików jako UTF-8, ale niestety nie jest to obsługiwane przez podstawową bibliotekę fmttaglib JSTL . Musiałbyś zarządzać tym wszystkim samodzielnie za pomocą pliku Filter. Istnieją struktury (MVC), które mogą sobie z tym poradzić w bardziej przejrzysty sposób, jak JSF, zobacz także ten artykuł .

BalusC
źródło
2
To fajne rozwiązanie ma jeden problem: locale pobrane z żądania mogą być językiem i krajem, jak w "en_US", co dałoby <html lang = "en_US">, czyli nieprawidłowy HTML. Konieczne jest użycie tylko części językowej „en” z ustawień regionalnych jako wartości atrybutu lang.
Torsten Römer
1
Przedstawiona powyżej metoda internacjonalizacji nie zmienia adresu URL na podstawie wyświetlanego języka. Czy masz jakieś sugestie, jak zaktualizować adres URL zgodnie z językiem. Pytam, ponieważ do indeksowania zaleca się, aby różne języki miały oddzielne adresy URL: support.google.com/webmasters/answer/…
theyuv
1
Jeśli umieścisz pliki zasobów językowych (pliki test.properties i text_en.properties) w katalogu głównym aplikacji / zasobów, możesz ustawić fmt: bundle w następujący sposób: <fmt: setBundle basename = "text" />
Bahadir Tasdemir
1
@bahadirT: zakładając, że „test” jest literówką, to prawda. basenameMusi reprezentować nazwę bazową bez rozszerzenia pliku. Brak strukturyzacji w pakiecie to tylko zła praktyka.
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

Oprócz tego, co powiedział BalusC, musisz zadbać o kierunkowość (ponieważ angielski jest zapisywany od lewej do prawej, a arabski odwrotnie). Najłatwiejszym sposobem byłoby dodanie diratrybutu do htmlelementu strony internetowej JSP i uzewnętrznienie go, aby wartość pochodziła z pliku właściwości (podobnie jak w przypadku innych elementów lub atrybutów):

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

Jest też kilka problemów ze stylizacją takiej aplikacji - należy co najmniej unikać pozycjonowania absolutnego. Jeśli z jakiegoś powodu nie możesz tego uniknąć, możesz albo użyć różnych arkuszy stylów dla (każdego?) Języka, albo zrobić coś, co jest dosłowne , czyli użyć tabel do zarządzania układem. Jeśli chcesz używać elementów div, sugerowałbym użycie względnego pozycjonowania z „symetrycznymi” atrybutami lewego i prawego stylu (oba mają tę samą wartość), ponieważ to właśnie sprawia, że ​​przełączanie kierunkowości działa.

Więcej informacji o witrynach dwukierunkowych można znaleźć tutaj .

Paweł Dyda
źródło
7
Tak, rzeczywiście, to również należy wziąć pod uwagę.
BalusC
4
<html dir="RTL">LUB <html dir="LTR">. Domyślnie jest to<html dir="LTR">
Fahim Parkar
2

Bazując na tym samouczku , używam na GAE - Google App Engine:

Plik jsp w następujący sposób:

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

I dodanie plików o nazwach: app.properties(domyślnie) i app_fr.properties(i tak dalej dla każdego języka). Każdy z tych plików powinien zawierać potrzebne ciągi, takie jak: klucz: wartość_w_ języku, np. app_fr.propertiesZawiera:

greeting=Bonjour!

app.properties zawiera:

greeting=Hello!

To wszystko

Ronen Rabinovici
źródło