thyleaf template form example engine java spring internationalization template-engine

java - template - thymeleaf spring



Internacionalización del correo electrónico usando Velocity/FreeMarker Templates (2)

Aquí está la solución (una plantilla, varios archivos de recursos) para Freemarker.

el programa principal

// defined in the Spring configuration file MessageSource messageSource; Configuration config = new Configuration(); // ... additional config settings // get the template (notice that there is no Locale involved here) Template template = config.getTemplate(templateName); Map<String, Object> model = new HashMap<String, Object>(); // the method called "msg" will be available inside the Freemarker template // this is where the locale comes into play model.put("msg", new MessageResolverMethod(messageSource, locale));

Clase MessageResolverMethod

private class MessageResolverMethod implements TemplateMethodModel { private MessageSource messageSource; private Locale locale; public MessageResolverMethod(MessageSource messageSource, Locale locale) { this.messageSource = messageSource; this.locale = locale; } @Override public Object exec(List arguments) throws TemplateModelException { if (arguments.size() != 1) { throw new TemplateModelException("Wrong number of arguments"); } String code = (String) arguments.get(0); if (code == null || code.isEmpty()) { throw new TemplateModelException("Invalid code value ''" + code + "''"); } return messageSource.getMessage(code, null, locale); }

}

Plantilla de Freemarker

${msg("subject.title")}

¿Cómo puedo lograr que i18n use un motor de plantillas como Velocity o FreeMarker para construir el cuerpo del correo electrónico?

Normalmente las personas tienden a crear plantillas como:

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

Y tener un paquete de recursos creado con propiedades como:

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

Esto crea un problema básico: si mis archivos .vm vuelven grandes con muchas líneas de texto, resulta tedioso traducir y administrar cada uno de ellos en archivos de paquete de recursos ( .properties ) separados.

Lo que estoy tratando de hacer es .vm archivo .vm separado para cada idioma, algo como mytemplate_en_gb.vm, mytemplate_fr_fr.vm, mytemplate_de_de.vm y luego de alguna manera decirle a Velocity / Spring que recoja el correcto en función de la entrada .

¿Es esto posible en primavera? ¿O debería estar buscando enfoques alternativos más simples y obvios?

Nota: Ya he visto el tutorial de Spring sobre cómo crear cuerpos de correo electrónico utilizando motores de plantillas. Pero no parece responder a mi pregunta en i18n.


Resulta que usar una plantilla y varios archivos language.properties gana sobre tener varias plantillas.

Esto crea un problema básico: si mis archivos .vm se vuelven grandes con muchas líneas de texto, resulta tedioso traducir y administrar cada uno de ellos en archivos de paquete de recursos (.properties) separados.

Es incluso más difícil de mantener si su estructura de correo electrónico está duplicada en varios archivos .vm . Además, habrá que reinventar el mecanismo de repliegue de los paquetes de recursos. Los paquetes de recursos intentan encontrar la coincidencia más cercana en un entorno local. Por ejemplo, si la configuración regional es en_GB , intenta encontrar los archivos a continuación en orden, retrocediendo al último si ninguno de ellos está disponible.

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

Publicaré (en detalle) lo que tuve que hacer para simplificar la lectura de paquetes de recursos en las plantillas de Velocity aquí.

Acceso al paquete de recursos en una plantilla de Velocity

Configuración de primavera

<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>

PlantillaHelper 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; } }

Plantilla de velocidad

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

Tuve que crear una macro de mano corta, msg para poder leer los paquetes de mensajes. Se parece a esto:

#** * 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

Paquete de recursos

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

Uso

Map<String, Object> data = new HashMap<String, Object>(); data.put("user", "Adarsh"); data.put("emailId", "[email protected]"); String body = templateHelper.merge("send-email.vm", data, locale);