I'm using Velocity and a message resource bundle to generate html pages. When I specify Mexico as my locale, my messages-es_MX.properties gets processed as the source for the message resources. This is as I expect it to be. But the characters (áéíóúüñ¿¡) aren't displayed properly.
My message property:
customer.greeting=áéíóúüñ¿¡
For my first attempt, I've got the following:
- html header in the generated page:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- velocity properties contains:
- input.encoding=utf-8
- output.encoding=utf-8
- html file encoding:
UTF-8
- messages_es_MX.properties encoding:
ISO-8859-1
Output to html for ${customer.greeting}
:
�������
I then realized that the encoding of the properties file isn't correct; it should also be UTF-8.
Second attempt:
- html header in the generated page:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- velocity properties contains:
- input.encoding=utf-8
- output.encoding=utf-8
- velocity properties contains:
- html file encoding:
UTF-8
- messages_es_MX.properties encoding:
UTF-8
Output to html:
áéÃóúüñ¿¡
Any suggestions on how to get this to work?
Well, this turned out to be trickier than I thought it would be, but here's the solution. Before beginning, ensure that all html and properties files are encoded in UTF-8. And that all Velocity configurations reference UTF-8 as well. There should be no references to ISO-8859-1.
The underlying problem is that by default,
ResourceBundle
assumes property files are inISO-8859-1
encoding. It's possible to override this, but takes a piece of custom code.Instead of calling
I needed to add an argument for a custom Control implementation:
The UTF8Control class looks like this:
Credit to @BalusC who originally posted this related answer.
So, part 1 solved. But there's still a problem, because I'm using VelocityTools and I can see in the source code for
ResourceTool
that it callsResourceBundle.getBundle(...)
without passing in any Control implementation. This means that it's going to use ISO-8859-1, and I have no way to pass in my UTF8Control...Unless I override the ResourceTool class's method to get the bundle:
In my UTF8ResourceTool class, I override just one method
getBundle
(and I had to copy a private method in verbatim from the parent class). The overridden method passes the UTFControl as the third argument when getting the resource bundle, so that we can pull in the resources using UTF-8 encoding.The only thing left now is to update my Velocity configuration so that I'm referencing my custom
UTF8ResourceTool
instead of Velocity Tools'ResourceTool
:Put it all together, and my html output for
${customer.greeting}
is: