Posted 22 days ago. Visible to the public. Repeats.

Rails: Including HTML in your i18n locales

TL;DR Append your locale keys with _html to have them marked as html_safe.


When you're localizing a Rails application, sometimes there is this urge to include a little HTML. Be it some localized link, or a set of <em> tags, you'd like to have it included in the locale file. Example:

Copy
# Locale file en: page: text: 'Please visit our <a href="https://www.corporate.com/en">corporate website</a> to learn more about <em>the corporation</em>.' # HAML = t('.text') # Desired output Please visit our <a href="https://www.corporate.com/en">corporate website</a> to learn more about <em>the corporation</em>. # Actually rendered as ... Please visit our <a href="www.corporate.com/en">corporate website</a> to learn more about <em>the corporation</em>. # ... which looks like this in the HTML source: Please visit our &lt;a href=&quot;https://www.corporate.com/en&quot;&gt;corporate website&lt;/a&gt; to learn more about &lt;em&gt;the corporation&lt;/em&gt;.

Alright. Rails is being helpful here and saves you from accidentally injecting HTML into the page. But how could you insert the desired HTML intentionally?
While blindly calling t(...).html_safe renders the text as desired, it removes the protection and leaves you vulnerable to rendering bad HTML

A workaround would be to split the translations around the HTML fragments.

Copy
= t('.please') = link_to t('.website'), t('.corporate_url') = t('.learn_more') = succeed '.' do %em = t('.corporation')

This is annoying, especially in HAML where you need the #succeed helper to end the line with a dot.

The solution

Fortunately, they've built something into Rails. Namely: The t() helper (but not I18n.t()) will mark translations as .html_safe if their key ends with _html:

Copy
# locale file en: page: text_html: 'Please visit our <a href="https://www.corporate.com/en">corporate website</a> to learn more about <em>the corporation</em>.' # HAML = t('.text_html') # Output Please visit our <a href="https://www.corporate.com/en">corporate website</a> to learn more about <em>the corporation</em>.

This will also properly escape unsafe interpolations:

Copy
# locale file en: page: text_html: 'Please visit our %{link} to learn more about <em>the corporation</em>.' # HAML = t('.text_html', link: '<script>alert("hacked")</script>') # Output Please visit our &lt;script&gt;alert(&quot;hacked&quot;)&lt;/script&gt; to learn more about <em>the corporation</em>.

makandra has been working exclusively with Ruby on Rails since 2007. Our laser focus on a single technology has made us a leader in this space.

Author of this card:

Avatar
Dominik Schöler
Last edit:
18 days ago
by Henning Koch
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Dominik Schöler to makandra dev