dojo 解决spring问题:javascript中的消息用于i18n国际化

wz3gfoph  于 2022-12-16  发布在  Dojo
关注(0)|答案(4)|浏览(172)

我正在尝试国际化我们的一些代码。我有一个JSPX页面,它使用<spring:message>标记来解析message.properties文件中的字符串。这对于JSPX页面中的HTML和CSS都很好用,但是那里有一个javascript文件,用<spring:message>标记替换那里的字符串只意味着它会被逐字打印出来。
我的JSPX源代码是这样的:

<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标记。
谢谢你的帮助!

jfewjypa

jfewjypa1#

在我看来,您要做的就是像对待JSP文件一样对待JS文件,并通过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属性
  • <spring:message />标记提供text属性是有意义的,因为它可以用作备用(如果给定语言没有翻译)以及注解(该元素代表什么)。
  • 为了防止Handlebar转义HTML内容,我使用了三个{{{curly braces}}}

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

ccrfmcuu

ccrfmcuu2#

感谢您的回答。下面是一个更通用的解决方案。
其思想是提供一个名为“string.js”的动态JavaScript文件,其中包含在Java资源包中注册的消息的关联数组,使用当前的用户语言。
1)在SpringController中创建一个方法,从资源包中加载所有资源键,并返回视图“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)实现视图“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”,但它将被缓存。当用户更改语言时,需要清除该高速缓存(或使用其他技巧重新加载文件)。

wfypjpf4

wfypjpf43#

除了@Toilal的答案之外,您还可以向strings.jsp添加一个helper函数,以便更好地使用转换数组:

<%@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"));
fslejnso

fslejnso4#

将spring的www.example.com转换message.properties为一个JavaScript对象,然后在其他JavaScript文件中使用该对象是非常简单的。

app.name=Application name
  app.description=Application description

字符串

const messages = { app: { name: 'Application name', description: 'Application description' } };

然后应该为每个messages.{lang}.properties创建一个messages_{lang}.js文件,并在模板中引用。在thymeleaf模板中,该文件如下所示:

<script th:src="@{'/js/messages_' + ${#locale}  + '.js'}"></script> 
  <script>
    console.log(messages.app.name, messages.app.description);
  </script>

为此,我创建了一个快速grunt plugin

相关问题