Posted 5 months 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>.

Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for old versions of Ruby on Rails (3.2 and 2.3).

Owner of this card:

Avatar
Dominik Schöler
Last edit:
5 months 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
This website uses cookies to improve usability and analyze traffic.
Accept or learn more