解决spring:用于i18n国际化的javascript消息
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决spring:用于i18n国际化的javascript消息相关的知识,希望对你有一定的参考价值。
我试图将我们的一些代码国际化。我在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}" />
我正在寻找替换字符串的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
}]);
最后,message.properties是这样的:
proj.settings.toggle=Click here to toggle
proj.settings.toggle.description=This toggles between on and off
所以我想知道的是,这应该有效吗?从我在各种论坛上收集到的内容来看,我似乎应该这样,但我无法弄清楚我哪里出错了。有没有更好的方法来解决这个问题?
我还应该注意这些文件在WEB-INF文件夹之外,但是通过将ReloadableResourceBundleMessageSource放在根applicationContext.xml中,可以获取spring标记。
谢谢你的帮助!
在我看来,你想要做的是将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}" />
在你的JS文件中:
buildList('settings', [{
name: strings['settings.toggle'],
id:"setting1",
description: strings['settings.toggle.description'],
installed: true
}]);
请注意,我使用双引号写出翻译的字符串。这是因为法语或意大利语中的一些词可能包含撇号。
编辑:附加输入
我们提供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>
在客户端(即在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);
这里有几点需要注意:
<spring:message />
标签默认转义为HTML和JS,我们不需要指定javaScriptEscape
属性- 为
text
标签提供<spring:message />
属性是有意义的,因为它可以用作后备(如果没有给定语言的翻译)以及注释(这个元素代表什么)。甚至可以创建一个工具来扫描<spring:message />
标签的文件并自动生成属性文件 - 为了防止Handlebars逃避HTML内容,我使用了三个
{{{curly braces}}}
基本上就是这样。如果可能,我建议使用模板。
感谢您的回答。这是一个更通用的解决方案。
我们的想法是提供一个名为“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());
}
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>
3)在HTML源代码中导入“spring.js”。 Messages数组可用并使用正确的语言加载。
可能的问题:如果用户更改了他的语言,导航器必须重新加载“spring.js”,但它将被缓存。当用户更改其语言(或其他技巧以重新加载文件)时,需要清除缓存。
除了回答@Toilal之外,您还可以向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>
/**
* Tranlate a String by key, if key is not defined return the key.
*
* @author Pedro Peláez <aaaaa976 at gmail dot com>, Drupal/Wordpress authors, and others
* @param {String} key
* @returns {String}
*/
function t(key) {
if (messages[key]) {
return messages[key];
}
return key;
}
然后在需要时使用:
alert(t("menu.section.main"));
将spring的message.properties转换为JavaScript对象然后在其他JavaScript文件中使用该对象非常简单。有一个node module我们可以改变
app.name=Application name
app.description=Application description
至
const messages = { app: { name: 'Application name', description: 'Application description' } };
然后应为每个消息创建messages_ {lang} .js文件。{lang} .properties并在模板中引用。在百里香叶模板中,它看起来像这样:
<script th:src="@{'/js/messages_' + ${#locale} + '.js'}"></script>
<script>
console.log(messages.app.name, messages.app.description);
</script>
我为此创造了一个快速的grunt plugin。
以上是关于解决spring:用于i18n国际化的javascript消息的主要内容,如果未能解决你的问题,请参考以下文章
从源码MessageSource的三个实现出发实战spring·i18n国际化