Решающая весна: сообщения в javascript для интернационализации i18n - PullRequest
25 голосов
/ 02 июня 2011

Я пытаюсь интернационализировать часть нашего кода.У меня есть страница в JSPX, которая использует тег <spring:message> для разрешения строк из файла message.properties.Это прекрасно работает для HTML и CSS, которые есть на странице JSPX, однако там есть файл 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
}]);

И, наконец, сообщение.properties это что-то вроде:

proj.settings.toggle=Click here to toggle
proj.settings.toggle.description=This toggles between on and off

Так что мне интересно, это должно работать?Из того, что я собрал на разных форумах, мне кажется, что так и должно быть, но я не могу понять, в чем дело.Есть ли лучший способ сделать это?

Я должен также отметить, что эти файлы находятся за пределами папки WEB-INF, но, поместив ReloadableResourceBundleMessageSource в корневой applicationContext.xml, пружинные теги подобраны.

Спасибо за любую помощь!

Ответы [ 4 ]

38 голосов
/ 05 июня 2011

Мне кажется, что вы хотите обработать файл 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.Обычно причина в том, что мы хотим динамически создавать некоторую часть пользовательского интерфейса.Также есть случаи, когда нам нужно локализовать какой-либо сторонний компонент, мой ответ выше вполне с ними справляется.
Для случаев, когда мы хотим создавать части пользовательского интерфейса динамически, действительно имеет смысл использовать шаблоны, а не объединять теги HTML вJavaScript.Я решил написать это, потому что это делает решение намного более чистым (и, возможно, многократно используемым).
Поэтому вместо передачи переводов в 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 /> и автоматически генерировал файлы свойств
  • . Чтобы не допустить выхода руля из содержимого HTML, я использовал тройной {{{curly braces}}}

в основном это.Я рекомендую использовать шаблоны, если это возможно.

20 голосов
/ 14 августа 2012

Спасибо за ваш ответ.Вот более общее решение.

Идея состоит в том, чтобы предоставить динамический файл javascript с именем "string.js", содержащий ассоциативный массив сообщений, зарегистрированных в пакете ресурсов 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) Импортировать "spring.js" в исходный код HTML.Массив сообщений доступен и загружен на нужном языке.

Возможная проблема : Если пользователь поменяет свой язык, навигатор должен перезагрузить «spring.js», но он будет кэширован.Очистка кеша необходима, когда пользователь меняет свой язык (или другой трюк для перезагрузки файла).

1 голос
/ 12 апреля 2017

В дополнение к ответу @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"));
0 голосов
/ 22 марта 2019

Довольно просто преобразовать свойство message.properties в Spring в объект JavaScript, а затем использовать этот объект в других файлах JavaScript. Есть модуль узла , с помощью которого мы можем преобразовать

  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 .

...