Velocity to FreeMarker Converter
Convert Liferay Velocity (.vm) templates to FreeMarker (.ftl) and back — directives, variables, and comments. Built for theme and ADT migration.
Conversion runs automatically as you type. This is a best-effort starting point — review the output, especially macro invocations (#name(...) ↔ <@name ... />) and comparison operators, which are not always auto-converted.
Velocity to FreeMarker — Why and When
Liferay moved away from Velocity starting in 7.0: themes, Application Display Templates (ADTs), web content templates, and email templates all use FreeMarker (.ftl) now. Migrating an older Liferay 6.x theme or a pile of legacy .vm templates means rewriting every directive and variable reference by hand — exactly the kind of mechanical work this converter does in one pass.
Velocity ↔ FreeMarker Syntax Reference
The core pattern mappings the converter applies. Keep this handy as a cheat sheet even when you are editing templates by hand.
| Pattern | Velocity | FreeMarker |
|---|---|---|
| Variable | $user.name | ${user.name} |
| Quiet / silent referenceSuppresses output when the value is missing. | $!user.name | ${user.name!} |
| Assign a variable | #set($x = 10) | <#assign x = 10> |
| If | #if($active) | <#if active> |
| Else if / else | #elseif($pending) #else | <#elseif pending> <#else> |
| Close ifVelocity reuses #end for every block; the converter tracks which block to close. | #end | </#if> |
| Foreach loop | #foreach($item in $list) | <#list list as item> |
| Close foreach | #end | </#list> |
| Loop indexFreeMarker exposes ?index (0-based) and ?counter (1-based). | $foreach.count / $velocityCount | ${item?counter} |
| Define a macro | #macro(greet $name) Hi $name #end | <#macro greet name>
Hi ${name}
</#macro> |
| Call a macroMacro INVOCATION differs and is not auto-converted — update calls by hand. | #greet($user) | <@greet user /> |
| Include a template | #parse("init.vm") | <#include "init.ftl"> |
| Line comment | ## a comment | <#-- a comment --> |
| Block comment | #* a comment *# | <#-- a comment --> |
How to Use This Converter
- Paste your Velocity. Drop your
.vmtemplate into the input panel, or click Load sample. - Read the FreeMarker output. It regenerates live as you type — no button to press.
- Check the flagged items. The tool highlights any Liferay-injected variables it detects so you can confirm they exist in your FreeMarker context.
- Fix macro calls by hand. Convert
#myMacro(args)to<@myMacro args />— invocations are intentionally left untouched. - Copy or download the result as a
.ftlfile.
Frequently Asked Questions
- Why convert Velocity to FreeMarker?
- Liferay deprecated Velocity in 7.0 and removed it in later releases. Themes, Application Display Templates (ADTs), and web content templates must use FreeMarker (.ftl). This tool gives you a fast, mechanical first pass at migrating existing .vm templates to FreeMarker syntax.
- What does the converter handle automatically?
- Directives (#set→<#assign>, #if/#elseif/#else→<#if>/<#elseif>/<#else>, #foreach→<#list>, #macro→<#macro>), the shared #end (resolved to the correct </#if>, </#list>, or </#macro> via a block stack), variable references ($x→${x}, $!x→${x!}), and comments (## and #* *# → <#-- -->).
- What do I still need to fix by hand?
- Macro invocations differ between the engines (Velocity #myMacro(args) vs FreeMarker <@myMacro args />) and are not auto-converted. Comparison operators inside conditions, built-in utilities, and any Java-side logic should also be reviewed. Treat the output as a strong starting point, not a guaranteed 1:1 port.
- Does it work in both directions?
- Yes. Use the swap button to convert FreeMarker back to Velocity. The Velocity-to-FreeMarker direction is the most reliable since that is the common Liferay migration path; the reverse is best-effort.
- Is my template uploaded anywhere?
- No. All conversion runs entirely in your browser. Your template code never leaves your device.