Как интернационализировать веб-приложение Java?

81

Я узнал от Google, что интернационализация - это процесс, с помощью которого я могу заставить свое веб-приложение использовать все языки. Я хочу понять Unicode для процесса интернационализации, поэтому я узнал о Unicode здесь и там .

Я могу понять Unicode, как набор символов кодируется в байтах, а байты снова декодируются в кодировку. Но я не знаю, как двигаться дальше. Я хочу узнать, как сравнивать строки, и мне нужно знать, как реализовать интернационализацию в моем веб-приложении. Любые предложения, пожалуйста? Пожалуйста, направь меня.

Моя цель:

Моя основная цель - разработать веб-приложение для перевода (с английского на арабский и наоборот). Я хочу следить за интернационализацией. Я хочу запустить свое веб-приложение для перевода во всех трех браузерах, а именно FF, Chrome, IE. Как мне этого добиться?

Я железный человек
источник

Ответы:

221

В случае базового веб-приложения JSP / сервлета основным подходом будет использование библиотеки тегов JSTL в сочетании с fmtпакетами ресурсов . Пакеты ресурсов содержат пары ключ-значение, где ключ является константой, которая одинакова для всех языков, а значение различается для разных языков. Пакеты ресурсов обычно представляют собой файлы свойств, которые загружаются ResourceBundleAPI. Однако это можно настроить так, чтобы вы могли загружать пары ключ-значение, например, из базы данных.

Вот пример того, как интернационализировать форму входа в ваше веб-приложение с пакетами ресурсов на основе файлов свойств.


  1. Создайте следующие файлы и поместите их в какой-нибудь пакет, например com.example.i18n (в случае Maven, поместите их в структуру пакета внутри src/main/resources).

    text.properties (содержит пары ключ-значение на языке по умолчанию, обычно английском)

     login.label.username = Имя пользователя
     login.label.password = Пароль
     login.button.submit = Войти
     

    text_nl.properties (содержит голландский (nl пары ключ-значение ))

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

    text_es.properties(содержит esпары "ключ-значение" испанский ( ))

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

    Имя файла пакета ресурсов должно соответствовать следующему шаблону name_ll_CC.properties. _llЧасть должна быть в нижнем регистре ISO 693-1 код языка. Это необязательно и требуется только при _CCналичии детали. _CCЧасть должна быть в верхнем регистре ISO 3166-1 Alpha-2 код страны. Это необязательно и часто используется только для различения языковых диалектов, характерных для конкретной страны, например американского английского ( _en_US) и британского английского ( _en_GB).


  2. Если это еще не сделано, установите JSTL. Если вы используете контейнер Servlet 2.5 или новее (Tomcat 6.0 и т. Д.) И web.xmlобъявлен соответствующим спецификации Servlet 2.5, просто поместите jstl-1.2.jar в /WEB-INF/libпапку webapp .


  3. Создайте следующий пример файла JSP и поместите его в папку веб-материалов.

    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">Управляет текущим языком. Если язык был указан в качестве параметра запроса (в раскрывающемся списке языков), он будет установлен. В противном случае, если язык уже был установлен в сеансе, придерживайтесь его. В противном случае используйте указанный пользователем языковой стандарт в заголовке запроса.

    <fmt:setLocale>Устанавливает стандарт для пакета ресурсов. Очень важно , чтобы эта линия перед<fmt:setBundle> тем .

    <fmt:setBundle>Инициализирует пакет ресурсов его базовым имя (то есть полное квалифицированное имя пакета , пока с единственным именем без _ll_CCспецификатора).

    В <fmt:message>Извлекает значение сообщений указанным расслоения ключа.

    Он <html lang="${language}">сообщает поисковым роботам, на каком языке находится страница, чтобы она не была помечена как дублирующийся контент (что хорошо для SEO).

    Раскрывающийся список языков будет немедленно отправлен JavaScript, когда будет выбран другой язык, и страница будет обновлена ​​с новым выбранным языком.


Однако следует помнить, что файлы свойств по умолчанию читаются с использованием кодировки символов ISO-8859-1. Вам нужно будет избежать их с помощью escape-кодов Unicode. Это можно сделать с помощью native2ascii.exeинструмента, поставляемого JDK . См. Также этот раздел статьи для более подробной информации.

Теоретической альтернативой было бы предоставление пакета с Controlвозможностью загрузки этих файлов как UTF-8, но, к сожалению, это не поддерживается базовой fmtбиблиотекой тегов JSTL . Вам нужно будет управлять всем этим самостоятельно с помощью файла Filter. Существуют (MVC) фреймворки, которые могут обрабатывать это более прозрачным образом, например JSF, см. Также эту статью .

BalusC
источник
2
У этого красивого решения есть одна проблема: локаль, взятая из запроса, может быть языком и страной, как в "en_US", что даст <html lang = "en_US">, что является недопустимым HTML. В качестве значения атрибута lang необходимо использовать только языковую часть «en» из локали.
Torsten Römer
1
Описанный выше метод интернационализации не изменяет URL-адрес в зависимости от отображаемого языка. У вас есть предложения, как обновить URL-адрес в соответствии с языком. Я спрашиваю, потому что для индексации рекомендуется, чтобы на разных языках были отдельные URL-адреса: support.google.com/webmasters/answer/…
theyuv
1
Если вы поместите файлы языковых ресурсов (файлы test.properties и text_en.properties) в корень приложения / ресурсов, вы можете установить пакет fmt: следующим образом: <fmt: setBundle basename = "text" />
Бахадир Тасдемир,
1
@bahadirT: если предположить, что "test" - опечатка, это правильно. basenameДолжны представлять собой имя базы без расширения файла. Не объединять его в пакет - плохая практика.
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

В дополнение к тому, что сказал BalusC, вы должны позаботиться о направленности (поскольку английский пишется слева направо, а арабский - наоборот). Самый простой способ - добавить dirатрибут к htmlэлементу вашей веб-страницы JSP и сделать его внешним, чтобы значение поступало из файла свойств (как и с другими элементами или атрибутами):

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

Кроме того, есть несколько проблем со стилизацией такого приложения - вам, мягко говоря, следует избегать абсолютного позиционирования. Если по какой-то причине вы не можете этого избежать, вы можете либо использовать разные таблицы стилей для (каждого?) Языка , либо сделать что-то запрещенное , то есть использовать таблицы для управления макетом. Если вы хотите использовать элементы div, я бы предложил использовать относительное позиционирование с «симметричными» атрибутами стиля левого и правого (оба имеют одинаковое значение), поскольку именно это заставляет переключение направленности работать.

Вы можете узнать больше о двунаправленных веб-сайтах здесь .

Павел Дыда
источник
7
Да, действительно, это тоже нужно учитывать.
BalusC
4
<html dir="RTL">ИЛИ <html dir="LTR">. По умолчанию<html dir="LTR">
Fahim Parkar
2

на основе этого руководства я использую следующее в GAE - Google App Engine:

Файл jsp следующего содержания:

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

И добавляем файлы с именами: app.properties(по умолчанию) и app_fr.properties(и так далее для каждого языка). Каждый из этих файлов должен содержать нужные вам строки, например: key: value_in_language, например, app_fr.propertiesсодержит:

greeting=Bonjour!

app.properties содержит:

greeting=Hello!

Это все

Ронен Рабинович
источник