考虑一个带有几个JavaScript文件的JSP应用程序。后端完全本地化,使用多个.properties
文件,每种语言一个。渲染的HTML包含正确语言的字符串 - 所有这些都是常用的东西并且运行得很好。
然而,现在我不时需要在JavaScript资源中使用一些本地化字符串。假设例如:
function foo() {
alert('This string should be localized!');
}
请注意,这有点类似于从JavaScript引用一些AJAX端点的需要,这是一个由反向JS路由器很好地解决的问题。然而,这里的关键区别是后端不使用路由器,但确实使用了字符串。
我提出了几种方法,但它们似乎都不够好。
呈现代码以调用foo()
的JSP将获取字符串:
foo('<%= localize("alert.text") %>');
function foo(alertText) {
alert(alertText);
}
优点:它有效。 缺点:方法签名臃肿。
JSP使用字符串呈现隐藏的跨度,JS获取它:
<span id="prototype" class="hidden">This string should be localized!</span>
function foo() {
alert($('#prototype').text());
}
优点:方法签名不再臃肿。
缺点:必须确保隐藏的<span>
始终存在。
有一个端点通过键调用字符串,JS调用它。 (代码是近似值。)
function foo() {
$.ajax({ url : '/ajax/localize', data : { key : 'alert.text' } })
.done(function(result) {
alert(result);
} );
}
优点:服务器可以完全控制本地化结果。 缺点:每个本地化字符串一次HTTP调用!任何AJAX调用都会失败,逻辑会中断。
这可以通过一次获得多个字符串来改善,但是rountrip问题是必不可少的。
包含当前语言的属性文件只是作为页面上的附加JS资源公开。
<script src="/locales/en.js" /> // brings in the i18n object
function foo() {
alert(i18n.alert.text);
}
优点:快速可靠。 缺点:所有字符串都被拉入 - 也是我们不需要或想要向用户公开的字符串。
这可以通过为JS保留一组单独的字符串来改进,但这违反了DRY原则。
这就是我所拥有的想法。它们都不是理想的,都有各自的问题。我目前正在使用前两种方法,并取得了不同程度的成功。还有其他选择吗?
答案 0 :(得分:1)
您对共享属性文件的想法是您建议的4个创意中最简洁的解决方案。我使用的一个流行的CMS叫做Silverstripe does the same thing,加载一个本地化的JS文件,将字符串添加到字典中,允许使用通用的API来检索字符串。
评论中提出的一点是关于为特定视图包含本地化字符串。虽然在特定情况下可以有一些用途,每个本地化有数千个字符串(总计超过几百KB),但也可能有点不必要。
根据您同时加载的其他JS资源的数量,您可能不希望每个视图有另一个请求只是为该语言环境添加更多字符串。每个视图的本地化都需要单独请求,这可能效率不高。在一个请求中为浏览器提供所有本地化,并让它只从每个视图的缓存中读取。
浏览器缓存完整的语言环境字符串集合可以带来更好的用户体验,页面加载时间更快,每个视图的请求少一个。对于移动用户来说,这可能非常有用,因为即使移动互联网速度更快,也不是每一个请求都是闪电般快速的。
如果您通过使用locale.asp
文件动态生成JS语言环境字符串来完成评论中建议的方法,那么您将为每个用户提供更多的工作。如果每个用户请求一次,这将不会那么糟糕,但如果它是每个视图的请求,它可能会开始加起来。
如果用户查看5个不同的页面,即服务器正在执行JSP的5倍,则为特定视图构建数据。虽然您的代码可能是基本的if语句并从文件系统加载一些文件,但执行该代码仍然存在开销。虽然每分钟10个请求可能不是问题,但每分钟可能会出现1,000个请求。
同样,额外的开销可能很小,但只是没有必要,除非你真的需要很多小的HTTP请求,而不是几个较大的HTTP请求和很少的浏览器缓存。
虽然这可能听起来像是过早优化,但我认为这是一个简单而重要的考虑因素。我们不知道您是否有5个用户或5,000个用户,您的用户是否会看到5个不同的视图或500个,是否会有很多/任何移动用户,您想要支持多少个区域设置,每个区域设置有多少个不同的字符串
因此我认为最好能够看到每个视图下载的语言环境字符串选择的大图。