Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7634709
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 31, 20262026-05-31T07:14:56+00:00 2026-05-31T07:14:56+00:00

How can I achieve i18n using a templating engine such as Velocity or FreeMarker

  • 0

How can I achieve i18n using a templating engine such as Velocity or FreeMarker for constructing email body?

Typically people tend to create templates like:

<h3>${message.hi} ${user.userName}, ${message.welcome}</h3>
<div>
   ${message.link}<a href="mailto:${user.emailAddress}">${user.emailAddress}</a>.
</div>

And have a resource bundle created with properties like:

message.hi=Hi
message.welcome=Welcome to Spring!
message.link=Click here to send email.

This creates one basic problem: If my .vm files becomes large with many lines of text, it becomes tedious to translate and manage each of them in separate resource bundle (.properties) files.

What I am trying to do is, have a separate .vm file created for each language, something like mytemplate_en_gb.vm, mytemplate_fr_fr.vm, mytemplate_de_de.vmand then somehow tell Velocity/Spring to pick up the right one based on the input Locale.

Is this possible in Spring? Or should I be looking at perhaps more simple and obvious alternative approaches?

Note: I have already seen the Spring tutorial on how to create email bodies using templating engines. But it doesn’t seem to answer my question on i18n.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-31T07:14:57+00:00Added an answer on May 31, 2026 at 7:14 am

    It turns out using one template and multiple language.properties files wins over having multiple templates.

    This creates one basic problem: If my .vm files becomes large with
    many lines of text, it becomes tedious to translate and manage each of
    them in separate resource bundle (.properties) files.

    It is even harder to maintain if your email structure is duplicated over multiple .vm files. Also, one will have to re-invent the fall-back mechanism of resource bundles. Resource bundles try to find the nearest match given a locale. For example, if the locale is en_GB, it tries to find the below files in order, falling back to the last one if none of them is available.

    • language_en_GB.properties
    • language_en.properties
    • language.properties

    I will post (in detail) what I had to do to simplify reading resource bundles in Velocity templates here.

    Accessing Resource Bundle in a Velocity template

    Spring Configuration

    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="content/language" />
    </bean>
    
    <bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">    
        <property name="resourceLoaderPath" value="/WEB-INF/template/" />
        <property name="velocityProperties">
            <map>
                <entry key="velocimacro.library" value="/path/to/macro.vm" />
            </map>
        </property>
    </bean>
    
    <bean id="templateHelper" class="com.foo.template.TemplateHelper">
        <property name="velocityEngine" ref="velocityEngine" />
        <property name="messageSource" ref="messageSource" />
    </bean>
    

    TemplateHelper Class

    public class TemplateHelper {
        private static final XLogger logger = XLoggerFactory.getXLogger(TemplateHelper.class);
        private MessageSource messageSource;
        private VelocityEngine velocityEngine;
    
        public String merge(String templateLocation, Map<String, Object> data, Locale locale) {
            logger.entry(templateLocation, data, locale);
    
            if (data == null) {
                data = new HashMap<String, Object>();
            }
    
            if (!data.containsKey("messages")) {
                data.put("messages", this.messageSource);
            }
    
            if (!data.containsKey("locale")) {
                data.put("locale", locale);
            }
    
            String text =
                VelocityEngineUtils.mergeTemplateIntoString(this.velocityEngine,
                    templateLocation, data);
    
            logger.exit(text);
    
            return text;
        }
    }
    

    Velocity Template

    #parse("init.vm")
    #msg("email.hello") ${user} / $user,
    #msgArgs("email.message", [${emailId}]).
    <h1>#msg("email.heading")</h1>
    

    I had to create a short-hand macro, msg in order to read from message bundles. It looks like this:

    #**
     * msg
     *
     * Shorthand macro to retrieve locale sensitive message from language.properties
     *#
    #macro(msg $key)
    $messages.getMessage($key,null,$locale)
    #end
    
    #macro(msgArgs $key, $args)
    $messages.getMessage($key,$args.toArray(),$locale)
    #end
    

    Resource Bundle

    email.hello=Hello
    email.heading=This is a localised message
    email.message=your email id : {0} got updated in our system.
    

    Usage

    Map<String, Object> data = new HashMap<String, Object>();
    data.put("user", "Adarsh");
    data.put("emailId", "adarsh@email.com");
    
    String body = templateHelper.merge("send-email.vm", data, locale);
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I know we can achieve this in VIM using nerdtree and gT and gt
Many people said that one can achieve higher performance by creating read-only and write-only
It is great that using Intermediate Language (.Net: MSIL, Java: Bytecode) we can achieve
It seems like you can achieve all you need with transactions using only BEGIN;
I know you can achieve something as privateness in JavaScript by using closures and
I have doubt whether we can achieve multiple inheritence using 'module' concept or Is
Im not sure how I can achieve this match expression. Currently I am using,
Using struct we can achieve all the functionalities of a class : constructors, destructors
I want a rich text box control using which i can achieve following functionality:
I would like to know how I can achieve the following using the nginx

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.