FreeMarker, as most Java applications, works with "UNICODE text" (UTF-16). Nonetheless, there are situations when it must deal with charsets, because it has to exchange data with the outer world that may uses various other charsets.
When FreeMarker has to load a template file (or an unparsed text file), then it must know the charset of the file, since files are just raw byte sequences. You can use the
encoding setting to specify the charset. This setting takes effect only when FreeMarker loads a template (parsed or unparsed) with the
getTemplate method of
Configuration . Note that the include directive uses this method internally, so the value of the
encoding setting is significant for an already loaded template if the template contains
include directive call.
The getter and setter method of the
encoding setting is special in the first (configuration) layer. The getter method guesses the return value based on a
Locale passed as parameter; it looks up the encoding in a table that maps locales to encodings (called encoding map), and if the locale was not found there, it returns the default encoding. You can fill the encoding map with the
setEncoding(Locale locale, String encoding) method of the configuration; the encoding map is initially empty. The default encoding is initially the value of the
file.encoding system property, but you always should set a default default with the
setDefaultEncoding method, rather than relying on that. For new projects, a popular default encoding is
You can give the charset directly by overriding the
encoding setting in the template layer or runtime environment layer (When you specify an encoding as the parameter of
getTemplate method, you override the
encoding setting in the template layer.). If you don't override it, the effective value will be what the
configuration.getEncoding(Locale) method returns for the effective value of the
Also, instead of relying on this charset guessing mechanism, you can specify the charset of the template in the template file itself, with the ftl directive, like
<#ftl encoding="utf-8"> .
Note that the charset of the template is independent from the charset of the output that the tempalte generates (unless the enclosing software deliberately sets the output charset to the same as the template charset).
output_encoding setting/variable and the url built-in is available since FreeMarker 2.3.1. It doesn't exist in 2.3.
In principle FreeMarker does not deal with the charset of the output, since it writes the output to a
java.io.Writer . Since the
Writer is made by the software that encapsulates FreeMarker (such as a Web application framework), the output charset is controlled by the encapsulating software. Still, FreeMarker has a setting called
output_encoding (starting from FreeMarker version 2.3.1). The enclosing software should set this setting (to the charset that the
Writer uses), to inform FreeMarker what charset is used for the output (otherwise FreeMarker can't find it out). Some features, such as the url built-in, and the output_encoding special variable utilize this information. Thus, if the enclosing software doesn't set this setting then FreeMarker features that need to know the output charset can't be used.
If you write software that will use FreeMarker, you may wonder what output charset should you choose. Of course it depends on the consumer of the FreeMarker output, but if the consumer is flexible regarding this question, then the common practice is either using the charset of the template file for the output, or using UTF-8. Using UTF-8 is usually a better practice, because arbitrary text may comes from the data-model, which then possibly contains characters that couldn't be encoded with the charset of the template.
FreeMarker settings can be set for each individual template processing if you use
Environment.process(...) instead of
Template.process(...) . Thus, you can set the
output_encoding setting for each template execution independently:
Writer w = new OutputStreamWriter(out, outputCharset); Environment env = template.createProcessingEnvironment(dataModel, w); env.setOutputEncoding(outputCharset); env.process();