Magnolia Freemarker渲染器i18n单引号未转义及扩展方案问询
Magnolia Freemarker i18n单引号转义问题解决指南
一、i18n对象的来源
Magnolia Freemarker渲染上下文里的i18n对象,并非通过contextAttributes配置项注入,而是由info.magnolia.rendering.freemarker.context.FreemarkerRenderingContext类在渲染器初始化时自动绑定到Freemarker上下文的核心对象,所以你在装饰器的contextAttributes配置中找不到它。
二、扩展i18n函数解决单引号转义问题
这里提供两种可落地的扩展方案:
方案1:自定义Freemarker指令包装原生i18n方法
通过自定义指令对i18n字符串做转义处理,不修改原生逻辑:
- 实现
TemplateDirectiveModel接口编写指令逻辑:
public class EscapedI18nDirective implements TemplateDirectiveModel { @Override public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException { // 从上下文获取原生i18n对象 I18nSupport i18n = (I18nSupport) env.getVariable("i18n"); String key = params.get("key").toString(); // 获取原始国际化字符串 String rawValue = i18n.get(key); // 转义HTML特殊字符+单引号,适配属性场景 String escapedValue = rawValue != null ? StringEscapeUtils.escapeHtml4(rawValue).replace("'", "'") : ""; // 输出处理后的内容 env.getOut().write(escapedValue); } }
- 在Magnolia配置中注册自定义指令:
在/modules/rendering/config/renderers/freemarker/contextAttributes节点下添加配置:
escapedI18n: class: com.your.module.package.EscapedI18nDirective scope: request
- 模板中调用自定义指令:
<@escapedI18n key="your.i18n.key" />
方案2:扩展原生I18nSupport类并替换上下文对象
直接替换原生i18n对象,模板无需修改调用方式:
- 继承
I18nSupport重写get()方法添加转义:
public class EscapedI18nSupport extends I18nSupport { public EscapedI18nSupport(I18nizer i18nizer, Locale locale) { super(i18nizer, locale); } @Override public String get(String key) { String rawValue = super.get(key); return rawValue != null ? StringEscapeUtils.escapeHtml4(rawValue).replace("'", "'") : null; } }
- 自定义
FreemarkerRenderingContext子类替换i18n对象:
public class CustomFreemarkerRenderingContext extends FreemarkerRenderingContext { public CustomFreemarkerRenderingContext(RenderingContext renderingContext, Configuration configuration) { super(renderingContext, configuration); } @Override protected void addContextVariables(Map<String, Object> context) { super.addContextVariables(context); // 替换原生i18n对象为自定义实现 I18nSupport originalI18n = (I18nSupport) context.get("i18n"); if (originalI18n != null) { context.put("i18n", new EscapedI18nSupport(originalI18n.getI18nizer(), originalI18n.getLocale())); } } }
- 通过装饰器替换渲染器的上下文实现:
在decorations/rendering/renderers/freemarker.yaml中配置:
class: info.magnolia.rendering.freemarker.FreemarkerRenderer contextClass: com.your.module.package.CustomFreemarkerRenderingContext
- 模板中继续使用原生调用方式即可:
${i18n.get('your.i18n.key')}
三、注意事项
- 转义逻辑可按需调整:如果是HTML文本内容场景,仅用
escapeHtml4即可;如果是HTML属性(如onclick)场景,需额外转义单引号为'。 - 自定义类需放在Magnolia模块的可扫描包下,确保类能被正确加载。
内容的提问来源于stack exchange,提问作者Jonathan
相关产品推荐
相关产品推荐

