formatjs / dust-intl

Dust helpers for internationalization.
http://formatjs.io/dust/
Other
48 stars 11 forks source link

formatMessage and html-formatting #60

Open sigmunau opened 8 years ago

sigmunau commented 8 years ago

I often find myself wanting to include a string with some formatting into a translated sentence. E.G "The user Sigmund performed this commit"

Looking at the source code it seems formatMessage allways performs html-escape (unless you hit the precompiled format optimization which doesn't and is probably a security issue...)

Recent versions of dustjs-linkedin allows you to return data from a helper and utilize the dustjs filters to do escaping. With this approach the following diff:

diff --git a/src/helpers.js b/src/helpers.js
index 2037abd..cc69305 100644
--- a/src/helpers.js
+++ b/src/helpers.js
@@ -240,14 +240,12 @@ function registerWith (dust) {

         // optimization for messages that have already been compiled
         if ('object' === typeof msg && 'function' === typeof msg.format) {
-            chunk.write(msg.format(params));
-            return chunk;
+            return msg.format(params);
         }

         formatOptions = contextGet(context, ['intl', 'formats']);
         locales = getLocales(chunk, params, context);
         formatter = getMessageFormat(msg, locales, formatOptions);
-        chunk.write(dust.escapeHtml(formatter.format(params)));
-        return chunk;
+        return formatter.format(params);
     }
 }

will allow formatMessage to be used like this:

{@formatMessage _key="mystring" user="<strong>Sigmund</strong>" filters="|u"/>

If filters are not set the default is still to html-escape, so it should be backwards compatible with existing templates.

santiagoaguiar commented 8 years ago

I'm facing the same issue. Our intl team is now loving working with react-intl and how we can easily let them tweak the messages, but we still need to split strings if they contain markup when using dust-intl.

Any chance that something like this suggestion could be accepted? Thanks!

sigmunau commented 8 years ago

For the record I ended up writing my own dust-helper like this:

            dust.helpers.blockTrans = function(chunk, context, bodies, params) {
                var template = context.get('_')[params.key];
                var subContext = {};
                for (var key in bodies) {
                    subContext[key] = "";
                }
                var tap = function(data) {
                    subContext[key] += data;
                    return "";
                };
                for (key in bodies) {
                    chunk.tap(tap).render(bodies[key], context).untap();
                }
                for (key in bodies) {
                    template = template.replace('{' + key + '}', subContext[key]);
                }
                chunk.write(template);
                return chunk;
            };

Which could be used from a template like this:

        {@blockTrans key="mandatory_clients_overview_more"}
            {:clients}
                {#clients}
                    <strong>{name}</strong>{@sep}, {/sep}
                {/clients}
            {:rest}
                {rest}
        {/blockTrans}

With a translation string like this: "This organization has listed some mandatory clients, such as {clients}, and {rest} more"