You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Magnolia Freemarker渲染器i18n单引号未转义及扩展方案问询

Magnolia Freemarker i18n单引号转义问题解决指南

一、i18n对象的来源

Magnolia Freemarker渲染上下文里的i18n对象,并非通过contextAttributes配置项注入,而是由info.magnolia.rendering.freemarker.context.FreemarkerRenderingContext类在渲染器初始化时自动绑定到Freemarker上下文的核心对象,所以你在装饰器的contextAttributes配置中找不到它。

二、扩展i18n函数解决单引号转义问题

这里提供两种可落地的扩展方案:

方案1:自定义Freemarker指令包装原生i18n方法

通过自定义指令对i18n字符串做转义处理,不修改原生逻辑:

  1. 实现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);
    }
}
  1. 在Magnolia配置中注册自定义指令:
    在/modules/rendering/config/renderers/freemarker/contextAttributes节点下添加配置:
escapedI18n:
  class: com.your.module.package.EscapedI18nDirective
  scope: request
  1. 模板中调用自定义指令:
<@escapedI18n key="your.i18n.key" />

方案2:扩展原生I18nSupport类并替换上下文对象

直接替换原生i18n对象,模板无需修改调用方式:

  1. 继承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("'", "&apos;") : null;
    }
}
  1. 自定义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()));
        }
    }
}
  1. 通过装饰器替换渲染器的上下文实现:
    在decorations/rendering/renderers/freemarker.yaml中配置:
class: info.magnolia.rendering.freemarker.FreemarkerRenderer
contextClass: com.your.module.package.CustomFreemarkerRenderingContext
  1. 模板中继续使用原生调用方式即可:
${i18n.get('your.i18n.key')}

三、注意事项

  • 转义逻辑可按需调整:如果是HTML文本内容场景,仅用escapeHtml4即可;如果是HTML属性(如onclick)场景,需额外转义单引号为&apos;。
  • 自定义类需放在Magnolia模块的可扫描包下,确保类能被正确加载。

内容的提问来源于stack exchange,提问作者Jonathan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 23:35:22