Разрешение spring: сообщения в javascript для интернационализации i18n
Я пытаюсь интернационализировать часть нашего кода. У меня есть страница в 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
}]);
И, наконец, 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.
Спасибо за любую помощь!
Ответы
Ответ 1
Мне кажется, что вы хотите обработать JS файл, такой как JSP файл, и разрешить его содержимое с помощью тега spring:.
Я бы этого не сделал.
Обычно 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 />
и автоматического создания файлов свойств
- Чтобы запретить использование Handlebars для экранирования содержимого HTML, я использовал triple
{{{curly braces}}}
Это в основном это. Я рекомендую использовать шаблоны, если это возможно.
Ответ 2
Спасибо за ваш ответ. Вот более общее решение.
Идея состоит в том, чтобы предоставить динамический файл 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. Массив сообщений доступен и загружен правильным языком.
Возможная проблема. Если пользователь меняет свой язык, "w761 > .js" должен быть перезагружен навигатором, но он будет кэшироваться. Очистка кеша необходима, когда пользователь меняет свой язык (или другой трюк, чтобы перезагрузить файл).
Ответ 3
В дополнение к ответу @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 her 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"));