Access resource bundle label with MVELAccess resource bundle label with MVEL

There’s an interesting question today from milonette, asking how to access labels with MVEL. Sometimes the Content Automation API doesn’t provide everything you need out of the box, hence the question. But the good news is this API is extensible.

While some functions are already available in the automation context, there is currently nothing to access the resource bundles. We’ll need to add our own function into it. This is quite easy to do. First we need to write the new function we need, then we’ll write an operation that adds this function to the content automation context.

Our localized function needs different parameters. We want the locale, the name of the resource bundle, the key of our message and some optional parameters. Here’s a simple implementation:

package org.nuxeo.sample;

import java.util.Locale;

import org.nuxeo.common.utils.i18n.I18NUtils;

public class LocalizationFunctions {

    public static String localize(String bundleName, String localeStr, String key, String... params) {
        Locale locale = Locale.forLanguageTag(localeStr);
        return I18NUtils.getMessageString(bundleName, key, params, locale);


Now that I have my function, I need to create an operation that will make this available within the automation context:

package org.nuxeo.sample;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.ecm.automation.OperationContext;
import org.nuxeo.ecm.automation.core.Constants;
import org.nuxeo.ecm.automation.core.annotations.Context;
import org.nuxeo.ecm.automation.core.annotations.Operation;
import org.nuxeo.ecm.automation.core.annotations.OperationMethod;

@Operation(id = AddLocalizationFunctions.ID, category = Constants.CAT_SCRIPTING, label = "AddLocalizationFunctions", description = "Add new function namespace to automation context.")
public class AddLocalizationFunctions {

    public static final String ID = "AddLocalizationFunctions";

    public static final String LOCALIZATION_FUNCTION_NAME = "LocFn";

    protected static final Log log = LogFactory.getLog(AddLocalizationFunctions.class);

    protected OperationContext ctx;

    public void run() {
        ctx.put(LOCALIZATION_FUNCTION_NAME, new LocalizationFunctions());


This should do the trick. Now if I do an operation chain starting with this operation, I’ll be able to use this function:

    <chain id="test2">
      <operation id="AddLocalizationFunctions"/>
      <operation id="Seam.AddInfoMessage">
        <param type="string" name="message">expr:LocFn.localize("messages", "en", "label.permalink.description",{"param1", "param2"})</param>

Notice the use of an inline MVEL array to comply with String… params argument. Now you can go wild and add any functions you want. In the future we’ll try to make this extensible through an extension point.