When using message bundles with <fmt:message> tags or using ordinary Java calls to get ResourceBundle messages, there is a very specific behavior with regards to single-quotes and replacement parameters.
By default, if <fmt:message> is used without replacement parameters ( <fmt:param> ), then the MessageFormat class is not used to render the message. This means that escaping of single-quotes (with two single-quotes) is not necessary for messages without replacement args. Here is the relevant excerpt of Apache's MessageSupport.java class (which is extended by the MessageTag):
message = bundle.getString( key );
// Perform parametric replacement if required
if ( !params.isEmpty() )
Object messageArgs = params.toArray();
MessageFormat formatter = new MessageFormat( "" ); // empty pattern, default Locale
formatter.applyPattern( message );
message = formatter.format( messageArgs );
The SimpleMessage in Stripes is always using the MessageFormat class to render messages. Because of this, there is a behavior inconsistency with regards to single-quotes. If you have a property declared in StripesResources as:
my.property.key=This Is The User's Message
The above property will be rendered as "This Is The User's Message" by <fmt:message>. However, SimpleMessage will render this message as "This Is The Users Message". SimpleMessage will strip out the single-quote. This is inconsistent behavior and means that quoted property messages cannot be re-used seamlessly between Stripes and regular JSTL <fmt> tags.
The necessary fix is for SimpleMessage to only use MessageFormat for rendering messages if the replacementParameters passed into it have a length greater than zero.