Resolving spring: messages en javascript pour l'internationalisation de i18n

j'essaie d'internationaliser une partie de notre code. J'ai une page dans JSPX qui utilise la balise <spring:message> pour résoudre les chaînes d'un fichier message.properties . Cela fonctionne très bien pour le HTML et le CSS qui est dans la page JSPX, cependant là un fichier javascript est source, et le fait de remplacer la balise <spring:message> pour la chaîne là signifie Juste qu'il est imprimé mot à mot.

Mon JSPX sources javascript comme ceci:

<spring:theme code="jsFile" var="js" />
<script type="text/javascript" src="${js}" />

La JS où je suis à la recherche de la remplacer, la chaîne est ci-dessous:

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
}]);

et enfin le message.propriétés est quelque chose comme:

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

donc ce que je me demande, est-ce que ça devrait marcher? Il me semble que ça devrait, d'après ce que j'ai trouvé sur différents forums, mais je ne peux pas comprendre où je vais mal. Est-il une meilleure façon d'aller à ce sujet?

je dois également noter que ces fichiers sont en dehors du dossier WEB-INF, mais en plaçant la source ReloadableResourceBundleMessageSource dans le contexte de l'application racine.xml les étiquettes de ressort sont ramassées.

Merci pour votre aide!

24
demandé sur olan 2011-06-02 22:51:34

3 réponses

il me semble que ce que vous voulez faire est de traiter le fichier JS comme le fichier JSP et résoudre son contenu via spring:message tag.

Je ne voudrais pas le faire.

typiquement JS i18n est fait de deux façons:

  • en écrivant le tableau des cordes traduites de la page JSP
  • en créant un filtre de traduction et fournir le fichier JS pré-traduit au client demandeur

les deux fonctionnent le mieux si vous créez un emplacement central pour vos cordes translables côté client.

Dans votre contexte, je recommande la première méthode (beaucoup plus facile). C'est à moins que votre projet soit assez grand et vous avez beaucoup de cordes traduisibles du côté du client. Donc la modification ressemblerait à:

<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}" />

et dans votre fichier JS:

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

Esprit vous que j'ai utilisé des guillemets doubles pour écrire des chaînes traduites. C'est à cause de quelques mots en français ou en italien qui pourraient contenir l'apostrophe.

modifier: entrée supplémentaire

nous fournissons des traductions aux fichiers JS pour la raison. Habituellement, la raison est que nous voulons créer une certaine partie de L'UI dynamiquement. Il y a aussi des cas où nous avons besoin de localiser une composante tierce partie, ma réponse ci-dessus les traite assez bien.

Pour les cas où nous voulons créer des parties D'UI de façon dynamique, il est vraiment logique d'utiliser des modèles plutôt que des balises HTML concaténées dans JavaScript. J'ai décidé d'écrire ceci, parce que cela rend la solution beaucoup plus propre (et peut-être réutilisable).

Ainsi, au lieu de passer des traductions à JavaScript, on peut créer un modèle et le mettre sur la page (Mon exemple utilisera guidon.js , mais je crois qu'il est possible d'utiliser n'importe quel autre moteur):

<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>

côté client (en JavaScript) tout ce que vous avez à faire est d'accéder au Modèle (exemple ci-dessous utilise évidemment jQuery) et compiler:

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);

peu de choses à noter ici:

  • <spring:message /> tags échapper à la fois HTML et JS par défaut, nous n'avons pas besoin de spécifier le javaScriptEscape attribut
  • Il judicieux de fournir text attribut <spring:message /> tag comme il pourrait être utilisé comme une solution de repli (si il n'y a pas de traduction pour une langue donnée) ainsi qu'un commentaire (ce que cet élément représente). On peut même créer un outil qui numériserait des fichiers pour les étiquettes <spring:message /> et générerait automatiquement des fichiers de propriétés
  • pour empêcher le guidon d'échapper au contenu HTML, j'ai utilisé le triple {{{curly braces}}}

c'est en gros ça. Je recommande d'utiliser des modèles si c'est possible.

38
répondu Paweł Dyda 2013-10-24 16:47:17

Merci pour votre réponse. Voici une solution plus générique.

l'idée est de fournir un JavaScript dynamique fichier nommé" chaîne.js", contenant un tableau associatif de messages enregistrés dans le Java resource bundle, en utilisant le langage utilisateur courant.

1) Créer une méthode au printemps contrôleur pour charger toutes les clés de ressources à partir de resource bundle, et retourner la vue" 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) implémenter les 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) Importation" printemps.js " dans votre code source HTML. Le tableau de Messages est disponible et chargé avec le bon langage.

problème : Si l'utilisateur de changer son langage, "le printemps.js" doit être rechargé par le navigateur, mais il sera mis en cache. Le nettoyage du cache est nécessaire lorsque l'utilisateur change sa langue (ou autre astuce pour obtenir le fichier reloaded).

20
répondu Toilal 2012-08-14 18:48:26

en plus de answer of @Toilal vous pouvez ajouter une fonction helper aux chaînes.jsp pour faire une meilleure utilisation de la traduction dans le tableau:

<%@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;
}

ensuite, si nécessaire, il suffit d'utiliser:

alert(t("menu.section.main"));
1
répondu Pedro Pelaez 2018-08-11 14:47:10