This blog is part of our Rails 6 series. Rails 6.0 was recently released.

Before Rails 6

Before Rails 6, keys with the _html suffix in the language locale files are automatically marked as HTML safe. These HTML safe keys do not get escaped when used in the views.

# config/locales/en.yml en : home : index : title_html : <h2>We build web & mobile applications</h2> description_html : We are a dynamic team of <em>developers</em> and <em>designers</em>. sections : blogs : title_html : <h3>Blogs & publications</h3> description_html : We regularly write our blog. Our blogs are covered by <strong>Ruby Inside</strong> and <strong>Ruby Weekly Newsletter</strong>.

<!-- app/views/home/index.html.erb --> <%= t ( '.title_html' ) %> <%= t ( '.description_html' ) %> <%= t ( '.sections.blogs.title_html' ) %> <%= t ( '.sections.blogs.description_html' ) %>

Once rendered, this page looks like this.

This way of marking translations as HTML safe by adding _html suffix to the keys does not work as expected when the value is an array.

# config/locales/en.yml en : home : index : title_html : <h2>We build web & mobile applications</h2> description_html : We are a dynamic team of <em>developers</em> and <em>designers</em>. sections : blogs : title_html : <h3>Blogs & publications</h3> description_html : We regularly write our blog. Our blogs are covered by <strong>Ruby Inside</strong> and <strong>Ruby Weekly Newsletter</strong>. services : title_html : <h3>Services we offer</h3> list_html : - <strong>Ruby on Rails</strong> - React.js ⚛ - React Native ⚛ 📱

<!-- app/views/home/index.html.erb --> <%= t ( '.title_html' ) %> <%= t ( '.description_html' ) %> <%= t ( '.sections.blogs.title_html' ) %> <%= t ( '.sections.blogs.description_html' ) %> <%= t ( '.sections.services.title_html' ) %> <ul> <% t ( '.sections.services.list_html' ). each do | service | %> <li> <%= service %> </li> <% end %> <ul>

The rendered page escapes the unsafe HTML while rendering the array of translations for the key .sections.services.list_html even though that key has the _html suffix.

A workaround is to manually mark all the translations in that array as HTML safe using the methods such as #raw or #html_safe .

<!-- app/views/home/index.html.erb --> <%= t ( '.title_html' ) %> <%= t ( '.description_html' ) %> <%= t ( '.sections.blogs.title_html' ) %> <%= t ( '.sections.blogs.description_html' ) %> <%= t ( '.sections.services.title_html' ) %> <ul> <% t ( '.sections.services.list_html' ). each do | service | %> <li> <%= service . html_safe %> </li> <% end %> <ul>

Arrays of translations are trusted as HTML safe by using the ‘_html’ suffix in Rails 6

In Rails 6, the unexpected behavior of not marking an array of translations as HTML safe even though the key of that array has the _html suffix is fixed.

# config/locales/en.yml en : home : index : title_html : <h2>We build web & mobile applications</h2> description_html : We are a dynamic team of <em>developers</em> and <em>designers</em>. sections : blogs : title_html : <h3>Blogs & publications</h3> description_html : We regularly write our blog. Our blogs are covered by <strong>Ruby Inside</strong> and <strong>Ruby Weekly Newsletter</strong>. services : title_html : <h3>Services we offer</h3> list_html : - <strong>Ruby on Rails</strong> - React.js ⚛ - React Native ⚛ 📱

<!-- app/views/home/index.html.erb --> <%= t ( '.title_html' ) %> <%= t ( '.description_html' ) %> <%= t ( '.sections.blogs.title_html' ) %> <%= t ( '.sections.blogs.description_html' ) %> <%= t ( '.sections.services.title_html' ) %> <ul> <% t ( '.sections.services.list_html' ). each do | service | %> <li> <%= service %> </li> <% end %> <ul>

We can see above that we no longer need to manually mark the translations as HTML safe for the key .sections.services.title_html using the methods such as #raw or #html_safe since that key has the _html suffix.

To learn more about this feature, please checkout rails/rails#32361.