有很多问题需要采取,而国际化应用的护理事情:
区域设置检测
您需要考虑的第一件事是检测终端用户的语言环境。根据你想要支持的内容,它可能很容易或者有点复杂。
- 正如您所知道的,网络浏览器倾向于通过HTTP Accept-Language头发送最终用户的首选语言。在Servlet中访问这些信息可能就像调用
request.getLocale()
一样简单。如果您不打算支持任何奇特Locale Detection workflow,您可能只需坚持这种方法。
- 如果您的应用程序中有用户配置文件,则可能需要为其添加首选语言和首选格式区域设置。在这种情况下,您需要在用户登录后切换区域设置。
- 您可能希望支持基于URL的语言切换(例如:http://deutsch.example.com/或http://example.com?lang=de)。您需要根据URL信息设置有效的区域设置 - 这可以通过各种方式完成(即URL过滤)。
- 你可能想要支持语言切换(从下拉菜单中选择它),但我不会推荐它(除非它与第3点结合)。
JSTL的做法可能是足够的,如果你只是想支持第一种方法,或者如果你不打算添加任何额外的依赖(如Spring框架)。
虽然我们在Spring框架有不少,你可以同时使用来检测地点(如CookieLocaleResolver,AcceptHeaderLocaleResolver,SessionLocaleResolver和LocaleChangeInterceptor)和外在的字符串和格式化的消息(见spring:message tab)几个不错的功能。
Spring Framework将允许您轻松实现上述所有场景,这就是为什么我更喜欢它。
字符串外部
这是应该很容易吧?那么,主要是 - 只需使用适当的标签。您可能要面对的唯一问题是外部化客户端(JavaScript)文本。有几种可能的方法,但让我提两个:
- 已经翻译的字符串的每个JSP编写阵列(信息标签),并简单地访问客户端代码阵列。这是更容易的方法,但不易维护 - 您需要从有效页面(实际引用客户端脚本的页面)中真正写入有效的字符串。之前我曾经这样做过,相信我,这不是你想要在大型应用程序中做的事情(但它可能是小型应用程序的最佳解决方案)。
- 另一种方法原则上听起来很难,但它实际上在未来更容易处理。这个想法是在客户端集中字符串(将它们移到一些常见的JavaScript文件中)。之后,您需要实现您自己的Servlet,并根据请求返回此脚本 - 应翻译内容。您将无法在此处使用JSTL,您需要直接从资源包中获取字符串。
维护起来要容易得多,因为您会有一个中心点来添加可翻译的字符串。
串连
我讨厌这样说,但级联从本地化的角度真的很痛苦。它们很常见,大多数人都没有意识到。
那么什么是串接呢?
从原理上讲,每个英语句子都需要翻译成目标语言。问题是,正确翻译的信息使用与其英文对应的不同顺序(因此英语“安全策略”被翻译为波兰语“Politykabezpieczeństwa” - “策略”是“polityka” - 顺序不同),它发生了很多次。
好的,但是它与软件有什么关系?
在Web应用程序,你可以连接字符串是这样的:
String securityPolicy = "Security " + "policy";
或像这样:
<p><span style="font-weight:bold">Security</span> policy</p>
两者会产生问题。在第一种情况下,您需要使用MessageFormat.format()
方法并将字符串外部化为(例如)"Security {0}"
和"policy"
,在后者中,您将外部化整个段落(p标记)的内容,,包括 span标记。我知道这对译者来说是痛苦的,但实际上没有更好的办法。
有时你必须在你的段落中使用动态内容--JSTL fmt:format标签也会在这里帮助你(它在后端侧工作在MessageFormat)。
布局
在本地化应用中,常常发生转换的字符串比那些英语长方式。结果可能看起来非常难看。不知何故,你需要修正样式。还有两种方法:
- 通过调整常见样式(并祈祷它不会破坏其他语言)来解决问题。这是非常痛苦的维护。
- 实现CSS本地化机制。我所谈论的机制应该提供默认的,与语言无关的CSS文件和每种语言的覆盖。这个想法是覆盖每种语言的CSS文件,以便您可以按需调整布局(仅适用于一种语言)。为此,默认CSS文件以及JSP页面不得在任何样式定义旁边包含
!important
关键字。如果您真的需要使用它,请将它们移动到基于语言的en.css - 这将允许其他语言修改它们。使用图形,颜色和声音,可能是特定的西方文化
文化的具体问题
避免。如果你真的需要它,请提供本地化的手段。避免使用方向敏感的图形(因为当你尝试本地化时会说阿拉伯语或希伯来语)。另外,不要以为整个世界都在使用相同的数字(即阿拉伯语并非如此)。
日期和时区
处理在Java中的时间日期是至少可以说是不容易的。如果您不打算支持除公历之外的任何内容,则可以使用内置的日期和日历类。 您可以使用JSTL fmt:timeZone,fmt:formatDate和fmt:parseDate在JSP中正确设置时区,格式和解析日期。
我强烈建议使用FMT:formatDate这样的:
<fmt:formatDate value="${someController.somedate}"
timeZone="${someController.detectedTimeZone}"
dateStyle="default"
timeStyle="default" />
这是隐蔽的日期和时间,重要的是有效的(最终用户)的时区。此外,将其转换为易于理解的格式非常重要 - 这就是为什么我建议使用默认格式样式。
顺便说一句。时区检测并不容易,因为网页浏览器不太好发送任何东西。相反,你可以首选时区字段添加到用户的偏好(如果有的话),或者获取当前时区通过客户端脚本从Web浏览器偏移(见Date object's methods)
数字和货币
号以及货币应该转换为本地格式。它是在类似的方式来完成的日期格式(解析也同样进行):
<fmt:formatNumber value="1.21" type="currency"/>
复合的消息
你已经被警告不要连接字符串。相反,你可能会使用MessgageFormat
。不过,我必须说明你应该尽量减少使用复合消息。这只是因为目标语法规则通常是不同的,所以译员可能不仅需要重新排列句子(这可以通过使用占位符和MessageFormat.format()
来解决),而是可以基于将被替换的语言以不同方式翻译整个句子。让我给你一些例子:
// Multiple plural forms
English: 4 viruses found.
Polish: Znaleziono 4 wirusy. **OR** Znaleziono 5 wirusów.
// Conjugation
English: Program encountered incorrect character | Application encountered incorrect character.
Polish: Program napotkał nieznaną literę | Aplikacja napotkała nieznaną literę.
字符编码
如果你打算本地化为不支持ISO 8859-1代码页的语言,你将需要支持Unicode - 最好的方法是将页面编码设置为UTF-8。我看到有人在做这样的:
<%@ page contentType="text/html; charset=UTF-8" %>
我必须提醒你:这是不够。实际上,你需要这样的声明:
<%@page pageEncoding="UTF-8" %>
此外,你还需要在页眉申报编码,只是为了安全起见:
<META http-equiv="Content-Type" content="text/html;charset=UTF-8">
我给你的名单并不详尽但这是一个很好的起点。祝你好运:)
[How to internationalize a java web applications。](http://stackoverflow.com/questions/4276061/how-to-internationalize-a-java-web-application) – BalusC