解决spring:用于i18n国际化的javascript消息

ola*_*lan 25 javascript dojo spring spring-mvc internationalization

我试图将我们的一些代码国际化.我在JSPX中有一个页面,它使用<spring:message>标记来解析message.properties文件中的字符串.这适用于JSPX页面中的HTML和CSS,但是有一个javascript文件来源,并且用<spring:message>标签替换那里的字符串只是意味着它逐字打印出来.

我的JSPX像这样来源javascript:

<spring:theme code="jsFile" var="js" />
<script type="text/javascript" src="${js}" />
Run Code Online (Sandbox Code Playgroud)

我正在寻找替换字符串的JS如下:

buildList('settings', [{
    name: '<spring:message code="proj.settings.toggle" javaScriptEscape="true" />',
    id:"setting1",
    description: '<spring:message code="proj.settings.toggle.description" javaScriptEscape="true" />',
    installed: true
}]);
Run Code Online (Sandbox Code Playgroud)

最后,message.properties是这样的:

proj.settings.toggle=Click here to toggle
proj.settings.toggle.description=This toggles between on and off
Run Code Online (Sandbox Code Playgroud)

所以我想知道的是,这应该有用吗?从我在各种论坛上收集到的内容来看,我似乎应该这样,但我无法弄清楚我哪里出错了.有没有更好的方法来解决这个问题?

我还应该注意这些文件在WEB-INF文件夹之外,但是通过将ReloadableResourceBundleMessageSource放在根applicationContext.xml中,可以获取spring标记.

谢谢你的帮助!

Paw*_*yda 38

在我看来,你想要做的是将JS文件视为JSP文件,并通过spring:message标签解析其内容.
我不会这样做.

通常JS i18n可以通过以下两种方式之一完成:

  • 通过从JSP页面写出已翻译的字符串数组
  • 通过创建翻译过滤器并向请求客户端提供预翻译的JS文件

如果您为客户端可翻译字符串创建一个中心位置,则两者都最有效.
在您的上下文中,我会推荐第一种方法(更容易).除非您的项目非常大并且您在客户端有很多可翻译的字符串,否则这是非常的.所以修改看起来像:

<script type="text/javascript">
  var strings = new Array();
  strings['settings.toogle'] = "<spring:message code='proj.settings.toggle' javaScriptEscape='true' />";
  strings['settings.toogle.description'] = "<spring:message code='proj.settings.toggle.description' javaScriptEscape='true' />";
</script>
<spring:theme code="jsFile" var="js" />
<script type="text/javascript" src="${js}" />
Run Code Online (Sandbox Code Playgroud)

在你的JS文件中:

buildList('settings', [{
    name: strings['settings.toggle'],
    id:"setting1",
    description: strings['settings.toggle.description'],
    installed: true
}]);
Run Code Online (Sandbox Code Playgroud)

请注意,我使用双引号写出翻译的字符串.这是因为法语或意大利语中的一些词可能包含撇号.

编辑:附加输入

我们提供JS文件的翻译.通常,原因是我们想要动态创建UI的某些部分.还有一些情况我们需要本地化一些第三方组件,我上面的答案很好地处理它们.
对于我们想要动态创建UI部分的情况,使用模板而不是在JavaScript中连接HTML标记确实很有意义.我决定写这个,因为它使得更清洁(并且可能是可重复使用的)解决方案.
因此,不是将翻译传递给JavaScript,而是可以创建模板并将其放在页面上(我的示例将使用Handlebars.js,但我相信可以使用任何其他引擎):

<script id="article" type="text/x-handlebars-template">
  <div class="head">
    <p>
      <span>
        <spring:message code="article.subject.header" text="Subject: " />
      </span>{{subject}}</p>
  </div>
  <div class="body">
    {{{body}}}
  </div>
</script>
Run Code Online (Sandbox Code Playgroud)

在客户端(即在JavaScript中),您所要做的就是访问模板(下面的示例显然使用jQuery)并编译:

var template = Handlebars.compile($("#article").html());
var html = template({subject: "It is really clean",
  body: "<p>Don't you agree?</p><p>It looks much better than usual spaghetti with JavaScript variables.</p>"
});
$("#someDOMReference").html(html);
Run Code Online (Sandbox Code Playgroud)

这里有几点需要注意:

  • <spring:message />标签默认转义为HTML和JS,我们不需要指定javaScriptEscape属性
  • text<spring:message />标记提供属性是有意义的,因为它可以用作后备(如果没有给定语言的翻译)以及注释(此元素代表什么).甚至可以创建一个工具来扫描文件中的<spring:message />标签并自动生成属性文件
  • 为了防止Handlebars逃避HTML内容,我使用了triple {{{curly braces}}}

基本上就是这样.如果可能,我建议使用模板.


Toi*_*lal 20

感谢您的回答.这是一个更通用的解决方案.

我们的想法是提供一个名为"string.js" 的动态javascript文件,其中包含使用当前用户语言在java资源包中注册的关联消息数组.

1)在Spring Controller中创建一个方法,从资源包中加载所有资源键,并返回视图"spring.jsp"

@RequestMapping(value="strings.js")
public ModelAndView strings(HttpServletRequest request) {
    // Retrieve the locale of the User
    Locale locale = RequestContextUtils.getLocale(request);
    // Use the path to your bundle
    ResourceBundle bundle = ResourceBundle.getBundle("WEB-INF.i18n.messages", locale);  
    // Call the string.jsp view
    return new ModelAndView("strings.jsp", "keys", bundle.getKeys());
}
Run Code Online (Sandbox Code Playgroud)

2)实现View "strings.jsp"

<%@page contentType="text/javascript" pageEncoding="UTF-8"
%><%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"
%><%@taglib prefix="spring" uri="http://www.springframework.org/tags"
%>var messages = new Array();

<c:forEach var="key" items="${keys}">messages["<spring:message text='${key}' javaScriptEscape='true'/>"] = "<spring:message code='${key}' javaScriptEscape='true' />";
</c:forEach>
Run Code Online (Sandbox Code Playgroud)

3)在HTML源代码中导入"spring.js".Messages数组可用并使用正确的语言加载.

可能的问题:如果用户更改了他的语言,导航器必须重新加载"spring.js",但它将被缓存.当用户更改其语言(或其他技巧以重新加载文件)时,需要清除缓存.