Search code examples
springurlfreemarker

Freemarker - compose language switch url


I am using freemarker template engine with Spring and I want to add or replace lang=xxx parameter in the href attribute of link element when rendering page.

The closest solution I have found is following:

<a href="${springMacroRequestContext.getRequestUri()}?lang=en'/>English</a>

But this is not sufficient when I have URL with parameters and fragments because I will miss them. For example http://localhost/sports/search?query=Volleyball&lang=cs#some-fragment results in http://localhost/sports/search?lang=en

How to compose the URL with added or changed lang parameter in freemarker and do not miss any part of requested URL?


Solution

  • I preferred to do it in Java, this simple implementation does not take into account hashes (#) or the presence of the given parameter in the url..

    public static String addParamToUrl(String url, String paramName, String paramValue){
        StringBuffer buffer = new StringBuffer(url);
        //adding separator
        if(url.indexOf('?') == -1){
            buffer.append('?');
        }else if(!url.endsWith("?") && !url.endsWith("&")){
            buffer.append('&');
        }        
    
        buffer.append(paramName);
        if(paramValue != null){
            buffer.append("=");
            buffer.append(URLEncoder.encode(paramValue, "UTF-8"));
        }
        return buffer.toString();
    }
    

    Put this method in a Class (i.e:Utils.java) that can be staticly accessed by Freemarker engine and than:

    <#assign url = Utils.addParamToUrl(springMacroRequestContext.getRequestUri(), "lang", "en") />
    
    <a href="${url}">English</a>
    

    To expose your Utils class you have to customize FreemarkerManager

    public class MyFreemarkerManager extends FreemarkerManager {
    
        public MyFreemarkerManager(){
            super();
        }
    
        @Override
        protected void populateContext(ScopesHashModel model, ValueStack stack, Object action, HttpServletRequest request, HttpServletResponse response) {
            super.populateContext(model, stack, action, request, response);
    
            try {
    
                BeansWrapper beansWrapper = new BeansWrapperBuilder(Configuration.VERSION_2_3_24).build();
                TemplateHashModel staticModels = beansWrapper.getStaticModels();
    
                TemplateHashModel utils = (TemplateHashModel)staticModels.get("com.package.Utils");
                model.put("Utils", utils);  
    
            } catch (TemplateModelException e) {
                //...
            }       
    
        }
    }
    

    Finally you have to tell Spring you are using MyFreemarkerManager as manager for Freemarker.