如何使Java Web应用程序国际化?


81

我从Google得知,国际化是使我的Web应用程序使用所有语言的过程。我想了解Unicode的国际化过程,因此我从这里那里了解了Unicode 。

我能够理解Unicode,即如何将一个字符集设置为编码为字节,然后再将字节解码为字符集。但是我不知道如何进一步前进。我想学习如何比较字符串,还需要知道如何在Web应用程序中实现国际化。有什么建议吗?请指导我。

我的目标:

我的主要目标是开发一个Web翻译应用程序(英语到阿拉伯语,反之亦然)。我想关注国际化。我希望在所有三种浏览器(即FF,Chrome,IE)中运行我的网络应用程序进行翻译。我该如何实现?

Answers:


221

对于基本的JSP / Servlet Web应用程序,基本方法是将JSTL fmttaglib资源包结合使用。资源束包含键/值对,其中键是一个常量,所有语言都相同,并且每种语言的值不同。资源束通常是属性文件,由ResourceBundleAPI。但是,可以对此进行自定义,以便您可以从例如数据库中加载键值对。

这是一个示例,该示例如何使用基于属性文件的资源包使您的Web应用程序的登录表单国际化。


  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 =使用权限
     login.label.password =对比
     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放在webapp的/WEB-INF/lib文件夹中。


  3. 创建以下示例JSP文件并将其放在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>
    

    <c:set var="language">管理当前语言。如果语言是作为请求参数提供的(通过语言下拉列表),则将对其进行设置。否则,如果会话中已经预先设置了语言,则请坚持使用。否则,请在请求标头中使用用户提供的语言环境。

    <fmt:setLocale>设置了资源包的语言环境。重要的是,这条线是之前<fmt:setBundle>

    <fmt:setBundle>通过其基本名称初始化资源包(即,完全限定的包名称,直到与没有唯一名称_ll_CC指定符)。

    所述<fmt:message>检索由指定捆密钥的消息值。

    <html lang="${language}">通知搜索引擎,指示该页面使用哪种语言,以使该页面不会被标记为重复内容(因此对SEO有利)。

    选择另一种语言后,JavaScript会立即提交语言下拉列表,并使用新选择的语言刷新页面。


但是,您需要记住,默认情况下使用ISO-8859-1字符编码读取属性文件。您将需要通过Unicode转义符对它们进行转义。这可以使用JDK提供的native2ascii.exe工具来完成。另请参阅本文部分以获取更多详细信息。

从理论上讲,替代方案是为捆绑包提供一个自定义,Control以将这些文件作为UTF-8加载,但是不幸的是,基本JSTL fmttaglib不支持该捆绑包。您将需要借助自己管理所有内容Filter。有(MVC)框架可以像JSF一样以更透明的方式处理此问题,另请参见本文


2
这个不错的解决方案有一个问题:从请求中获取的语言环境可以是语言和国家/地区,例如“ en_US”,这将给出<html lang =“ en_US”>,这是无效的HTML。只需要使用语言环境中的语言部分“ en”作为lang属性的值。
TorstenRömer2013年

1
上面概述的国际化方法不会根据显示的语言修改网址。您是否对根据语言更新网址有任何建议?我要问一下,因为对于索引编制,建议不同的语言使用单独的网址:support.google.com/webmasters/answer/…–
它们

1
如果将语言资源(test.properties和text_en.properties文件)文件放在应用程序/资源根目录,则可以这样设置fmt:bundle:<fmt:setBundle basename =“ text” />
Bahadir Tasdemir

1
@bahadirT:假设“测试”是一个错字,那是正确的。将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属性添加到htmlJSP网页的元素并将其外部化,因此该值来自属性文件(就像其他元素或属性一样):

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

同样,对这种应用程序进行样式设置几乎没有问题-您至少应该避免绝对定位。如果由于某种原因无法避免这种情况,则可以使用每种语言(每种语言)使用不同的样式表,或者执行verboten的操作,即使用表格来管理布局。如果要使用div元素,我建议使用带有“对称”左右样式属性(两者都具有相同值)的相对定位,因为这使切换方向性起作用。

您可以在此处找到有关双向网站的更多信息。


7
是的,的确,也必须考虑到这一点。
BalusC,2010年

4
<html dir="RTL"><html dir="LTR">。默认值为<html dir="LTR">
Fahim Parkar 2012年

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!

就这样


10
g,脚本!
Nestor Hernandez Loli 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.