在JSP/Servlet和HTML5/JavaScript Web应用程序中使用本地化字符串支持多种语言



我有一个使用JSP/Servlet框架编写的web动态项目,客户端使用HTML5/CSS和JavaScript。这意味着服务器端编程语言是Java(JSP页面的标准或scriptlet内部),而客户端编程语言是JavaScript。

我需要一种方法来管理为多种语言翻译的字符串(例如,英语、意大利语、西班牙语、法语…),这些字符串必须根据用户使用的语言(即浏览器的语言)使用。我可以通过为每种语言定义一个字符串列表来做到这一点,例如为每种种语言使用一个XML文件,如下例:

<!-- File: en-US.xml -->
<list lang="en-US">
    <string>
        <key>hello</key>
        <value>Hello!</value>
    </string>
</list>
<!-- File: es-ES.xml -->
<list lang="es-ES">
    <string>
        <key>hello</key>
        <value>¡Hola!</value>
    </string>
</list>
<!-- File: it-IT.xml -->
<list lang="it-IT">
    <string>
        <key>hello</key>
        <value>Ciao!</value>
    </string>
</list>

通过这种方式,我可以从JavaScript或JSP/Servlet中使用该文件,并获取字符串。这可能意味着我需要两个方法:第一个在服务器端使用(Servlet和JSP),第二个在客户端使用。但我不确定是否有一种独特的方法可以做到这一点。

我的问题是:

  • 在JSP/Servlet/JavaScript web应用程序中管理本地化字符串的最佳方式是什么?是否有一些预定义的方法,利用了一些API的优势
  • 有没有一种方法可以做到这一点,即在一个文件中为每种语言定义字符串,并从JSP/Servlet和JavaScript中同时使用它们

在服务器端使用您想要的任何技术。您可以拥有所述的xml文件,也可以使用基于ResourceBundle的java中包含的标准i18n。在这种情况下,您可以为每种语言创建属性文件(请参阅http://docs.oracle.com/javase/tutorial/i18n/resbundle/propfile.html看看如何做到这一点)。

现在,在java/servlet中,您首先通过访问request.getLocales来读取浏览器发送给您的区域设置(http://docs.oracle.com/javaee/6/api/javax/servlet/ServletRequest.html#getLocales%28%29)

在浏览器中使用了语言环境后,在java/servlet中,您可以以"标准"的方式读取翻译,因此在ResourceBundle的情况下,您可以像这样进行

Locale locale = getLocaleBasingOnRequest(HttpServletRequest request); // read the locale sent by browser by accesing request.getLocales()
ResourceBundle bundle = ResourceBundle.getBundle("Translations_file", locale);
for (String key : bundle.keySet()) {
  System.out.println(key);
  System.out.println(bundle.getString(key));
}

现在,为了在javascript中获得相同的翻译,您可以动态地将翻译输出到javascript文件中。例如,您可以创建TranslationsServlet,它将javascript翻译输出到javascript数组。

public class TranslationServlet extends javax.servlet.http.HttpServlet {

      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          Locale locale = getLocaleBasingOnRequest(HttpServletRequest request); // read the locale sent by browser by accesing request.getLocales()
          ResourceBundle bundle = ResourceBundle.getBundle("Translations_file", locale); // get the tranlation strings
          resp.getWriter().println("var translations = new Object();");
          for (String key : bundle.keySet()) {
              resp.getWriter().println("translations["" + key + ""] = "" +   bundle.getString(key) + "";");
          }
      }
}

上面的servlet应该动态生成带有翻译的javascript文件,所以它应该输出如下内容:

var translations = new Object();
translations["key1"] = "Test";
translations["key2"] = "Test2";

有了这种动态翻译,你只需添加javascript脚本标签:就可以将它们包含在你的每个html页面中

<script type="text/javascript" src="/translations-servlet" />

之后,您可以访问javascript代码中的翻译数组,因此您可以简单地通过以下代码访问它们:

for(var key in translations)
{
  document.write("for " + key + " the tranlations is " + translations[key]);
}

一个简单的解决方案是在服务器端使用ResourceBundle。您只需将所有语言翻译文件放在类路径的同一目录中,例如/org/example/nls/ihm.propertiesLocale.ROOT/org/example/nls/ihm_fr.propertiesLocale.FRENCH/org/example/nls/ihm_de.propertiesLocale.GERMAN

保存区域设置的常见方法是将其名称存储在会话属性中,例如LOCALE

然后您可以从servlet轻松地访问它们:

String localeName = request.getSession().getAttribute("LOCALE");
if (localeName == null) { localeName = Locale.ROOT; }
Locale locale = new Locale(request.getSession);
ResourceBundle bundle = ResourceBundle.getBundle("org.sba.nls.ihm", locale);
String cancel = bundle.getString("CANCEL"); // gives Annuler (value from ihm_fr)

如果您要求提供一个没有提供翻译的区域设置,那么最终将使用JVM默认区域设置。我的建议是在初始化代码中的某个位置使用Locale.setDefault(Locale.ROOT);,以确保将ihm用于未知的区域设置。

使用JSTL:的JSP文件几乎同样简单

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
...
<jsp:useBean id="LOCALE" scope="session" class="java.lang.String"/>
<fmt:setLocale value="${LOCALE}"/>
<fmt:setBundle basename="org.example.nls.ihm" var ="ihm"/>
...
<fmt:setBundle basename="org.sba.nls.ihm" var ="ihm"/>
<fmt:message key="CANCEL" bundle="${ihm}"/>

当然,由于翻译文件在服务器端,您不能直接在客户端javascript上使用它们。但是您可以很容易地使用JSP生成包含有用翻译的JSON字符串:

<%@page contentType="application/json" pageEncoding="UTF-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<jsp:useBean id="LOCALE" scope="session" class="java.lang.String"/>
<fmt:setLocale value="${LOCALE}"/>
<fmt:setBundle basename="org.sba.nls.ihm" var ="ihm"/>
{ CANCEL: <fmt:message key="CANCEL" bundle="${ihm}"/> }

然后,您可以从客户端javascript获取它,并将其用于翻译

最新更新