Migrate from the Properties Plugin to Resource Bundles
You can migrate from the Properties Plugin to Resource Bundles by running a Groovy updater script that converts your properties documents into a resource bundle document.
Migration Steps
- Create a new resource bundle document in your preferred folder.
- Add the provided Groovy script to your script registry.
- Set the
pathparameter to the absolute path of the resource bundle document you created. For example:/content/documents/myproject/labels/labels - Run the script. Before running it on production data, consider performing a dry run. Ensure that there are no conflicting keys in your properties documents.
- Review the resource bundle document. The script should add all properties from your existing properties documents to the resource bundle.
- Update your codebase to retrieve messages from the resource bundle instead of the properties documents.
Groovy Updater Script
The following script searches for all properties:properties documents, reads their properties, and writes them to the specified resource bundle document.
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); keys.add(key); for (String langKey : values.keySet()) { if ("en".equals(langKey)) { messages.add(values.get(langKey)); } else if ("fr".equals(langKey)) { messages_fr.add(values.get(langKey)); } } if (messages.size() < messages_fr.size()) { log.debug "Missing English label for ${key}, inserting empty label" messages.add(""); } else if (messages_fr.size() < messages.size()) { log.debug "Missing French label for ${key}, inserting empty label" messages_fr.add(""); } } 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"); } }
Next Steps
After migrating the properties, update your application code to use the resource bundle messages. Verify that all required keys are present and that there are no duplicate or missing translations.
If you encounter issues, review the script output and ensure that your resource bundle document contains the expected keys and values.