Migrate from the Properties Plugin to Resource Bundles - BloomReach Experience - Open Source CMS

This article covers a Hippo CMS version 12. There's an updated version available that covers our most recent release.


Migrate from the Properties Plugin to Resource Bundles

To migrate from the Properties Plugin to Resource Bundles, you can use a Groovy updater script to convert your properties documents to a resource bundle.

  1. Create a resource bundle document in a folder of your choice.

  2. Add the Groovy script below to the script registry.

  3. Set the 'path' parameter to the absolute path of the resource bundle document your created, e.g. /content/documents/myproject/labels/labels.

  4. Run the script! You might want to do a dry run first. Make sure you have no conflicting keys.

  5. Check your resource bundle document. All properties from all your properties documents should have been added to the resource bundle.

  6. You will still need to adapt your code to use the messages from the resource bundle instead of the properties documents.

package org.hippoecm.frontend.plugins.cms.dev.updater
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import org.onehippo.repository.update.BaseNodeUpdateVisitor;
 * Looks up all properties:properties documents, reads the properties in them,
 * and writes them to the specified resource bundle document.
class PropertiesToResourceBundleConverter extends BaseNodeUpdateVisitor {
  public boolean doUpdate(Node node) {
    log.debug "Updating node ${node.path}"
    Map<String, Map<String, String>> labels = new HashMap<String, Map<String, String>>();
    QueryManager qm = node.getSession().getWorkspace().getQueryManager();
    Query query = qm.createQuery("/jcr:root/content//element(*,properties:properties)", Query.XPATH);
    QueryResult result = query.execute();
    NodeIterator propertyDocumentNodes = result.getNodes();
    while (propertyDocumentNodes.hasNext()) {
      Node propertyDocumentNode = propertyDocumentNodes.nextNode();
      log.debug "Processing properties document ${propertyDocumentNode.getPath()}";
      String lang = "en";
      if (propertyDocumentNode.hasProperty("hippotranslation:locale")) {
        String locale = propertyDocumentNode.getProperty("hippotranslation:locale").getString();
        if (locale != null && locale.startsWith("fr")  ) {
          lang = "fr";
      NodeIterator propertyNodes = propertyDocumentNode.getNodes("properties:property");
      while (propertyNodes.hasNext()) {
        Node propertyNode = propertyNodes.nextNode();
        if (propertyNode.hasProperty("properties:name") && propertyNode.hasProperty("properties:value")) {
          String name = propertyNode.getProperty("properties:name").getString();
          String value = propertyNode.getProperty("properties:value").getString();
          log.debug "Convert property ${name}=${value} (${lang})";
          if (!labels.containsKey(name)) {
            Map<String, String> values = new HashMap<String, String>();
            values.put(lang, value);
            labels.put(name, values);
          } else {
            if (labels.get(name) == null) {
              labels.put(name, new HashMap<String, String>());
            Map<String, String> values = labels.get(name);
            if (!values.containsKey(lang)) {
              values.put(lang, value);
            } else {
              // error!
              log.debug "duplicate key detected ${lang}:${value}";
    if (labels.size() > 0) {
      List<String> keys = new ArrayList<String>();
      List<String> messages = new ArrayList<String>();
      List<String> messages_fr = new ArrayList<String>();
      for (String key : labels.keySet()) {
        Map<String,String> values = labels.get(key);
        for (String langKey : values.keySet()) {
            if ("en".equals(langKey)) {
            } else if ("fr".equals(langKey)) {
        if (messages.size() < messages_fr.size()) {
          log.debug "Missing English label for ${key}, inserting empty label"
        } else if (messages_fr.size() < messages.size()) {
          log.debug "Missing French label for ${key}, inserting empty label"
      log.debug "Number of keys: ${keys.size()}";
      log.debug "Number of English messages: ${messages.size()}";
      log.debug "Number of French messages: ${messages_fr.size()}";
      node.setProperty("resourcebundle:keys", (String[]) keys.toArray());
      node.setProperty("resourcebundle:messages", (String[]) messages.toArray());
      node.setProperty("resourcebundle:messages_fr", (String[]) messages_fr.toArray());
    return false;
  public boolean undoUpdate(Node node) {
      throw new UnsupportedOperationException("Updater does not implement undoUpdate method");
Did you find this page helpful?
How could this documentation serve you better?
On this page
    Did you find this page helpful?
    How could this documentation serve you better?