45

Can you do the following with a Java ResourceBundle?

In the properties file...

example.dynamicresource=You currently have {0} accounts.

At runtime...

int accountAcount = 3;
bundle.get("example.dynamicresource",accountCount,param2,...);

To give a result of

"You currently have 3 accounts."

benstpierre
  • 32,833
  • 51
  • 177
  • 288

8 Answers8

79

Not without using the MessageFormat class, such as:

String pattern = bundle.getString("example.dynamicresource");
String message = MessageFormat.format(pattern, accountCount);
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
David Sykes
  • 7,131
  • 4
  • 36
  • 39
11

On their own, ResourceBundle does not support property placeholders. The usual idea is to take the String you get from the bundle, and stick it into a MessageFormat, and then use that to get your parameterized message.

If you're using JSP/JSTL, then you can combine <fmt:message> and <fmt:param> to do this, which uses ResourceBundle and MessageFormat under the covers.

If you happen to be using Spring, then it has the ResourceBundleMessageSource which does something similar, and can be used anywhere in your program. This MessageSource abstraction (combined with MessageSourceAccessor) is much nicer to use than ResourceBundle.

Beryllium
  • 12,808
  • 10
  • 56
  • 86
skaffman
  • 398,947
  • 96
  • 818
  • 769
6

There are various ways, depending on the view technology you're using. If you're using "plain vanilla" Java (e.g. Swing), then use MessageFormat API as answered before. If you're using a webapplication framework (which is true, if I judge your question history here correctly), then the way depends on the view technology and/or MVC framework you're using. If it is for example "plain vanilla" JSP, then you can use JSTL fmt:message for this.

<fmt:message key="example.dynamicresource">
    <fmt:param value="${bean.accountCount}">
</fmt:message>

If it is for example JSF, you can use h:outputFormat for this.

<h:outputFormat value="#{bundle['example.dynamicresource']}">
    <f:param value="#{bean.accountCount}">
</h:outputFormat>

Best place is to just consult the documentation of the technology/framework you're using (or to tell it here so that we can give better suited and more detailed answers).

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
3

Struts have a nice util called MessageResources which does exactly what you ask for....

e.g.

MessageResources resources = getResources(request, "my_resource_bundle"); // Call your bundle exactly like ResourceBundle.getBundle() method
resources.getMessage("example.dynamicresource",accountCount,param2,...);

Limitation It only allows maximum of 3 parameters (i.e. resource attribute, param1, ..., param3).

I suggest using MessageFormat (if you want to use more than 3 parameter values) as suggested by David Sykes.

PS the getResources method is available only in the Struts Action class.

Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
  • **As a note/update**: The Struts 1.x web framework has reached its [end of life](http://struts.apache.org/struts1eol-press.html) and is no longer officially supported since May 2013. – informatik01 Mar 11 '15 at 17:04
  • **As an addition**: Struts 2 provides a better alternative in the form of *getText()* methods. Those methods are defined in the [*TextProvider*](http://struts.apache.org/maven/xwork-core/apidocs/index.html?com/opensymphony/xwork2/TextProvider.html) interface, which *ActionSupport* class implements. There are two *getText()* methods that support message parameter substitution: one that takes an array and one that takes a list, and both do not have any (reasonable) limitations on the number of parameters. – informatik01 Mar 11 '15 at 17:11
  • @informatik01 though your answer is valid at this moment, this answer was posted in March 2010, when Struts 1.x was *still* supported. – Buhake Sindi Mar 12 '15 at 02:21
  • I know, that's why I marked the first comment as an **update**. And I was not trying to compromise your answer, it's just a *note for others who are not aware of those changes*. No offense :-) – informatik01 Mar 12 '15 at 11:05
1

I don't think you can make this work for Non-English properties file.

My message.properties file has the following line:

info.fomat.log.message.start=Starting to parse log message in {0} format.

And my message_fr_FR.properties file has the following line:

info.fomat.log.message.start=A partir d'analyser le message connecter {0} format.

This code works only for the English one

String.format((String) messages .getString(GlobalConstants.MESSAGE_FORMAT_START), GlobalConstants.STR_JSON));

It does NOT replace the placeholder with the value when my language / locale is French :-(

Even MessageFormat.fomat() is no good

MRay
  • 11
  • 1
  • When using String.format(..) you can use classical C format format specifiers like '%d', '%s'. – digital_infinity Oct 22 '12 at 12:55
  • 1
    MRay: It seems that the single quote in your French text may be the problem according to the answer by @tleveque. What happens When you change your string to info.fomat.log.message.start=A partir d''analyser le message connecter {0} format. – Brendon Dugan Feb 19 '14 at 15:52
0

Remember that when using MessageFormat.format() you need to use a double quote ('') in your resource bundle if you want to express single quote (').

john_science
  • 6,325
  • 6
  • 43
  • 60
tleveque
  • 507
  • 3
  • 9
  • 16
0

I don't believe ResourceBundle can do that itself, but String can:

String.format(bundle.getString("example.dynamicresource"), accountCount);
tom
  • 1,017
  • 6
  • 12
0

MessageFormoat#format will work for the case like:

greetingTo=Have Param, saying hello {0}

You can declare two methods like this where RB is a instance of ResourceBundle:

/**This is a method that takes the param to substitute the placeholder**/
public String getString(String key, Object... params  ) {
    try {
        return MessageFormat.format(this.RB.getString(key), params);
    } catch (MissingResourceException e) {
        return "[" + key + "]";
    }
}

/**Without a param, this will derectly delegate to ResourceBundle#getString**/
public String getString(String key) {
    try {
        return this.RB.getString(key);
    } catch (MissingResourceException e) {
        return "[" + key + "]";
    }
} 
JaskeyLam
  • 15,405
  • 21
  • 114
  • 149