This blog is part of our Rails 6 series.
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.
1# config/locales/en.yml 2 3en: 4 home: 5 index: 6 title_html: <h2>We build web & mobile applications</h2> 7 description_html: 8 We are a dynamic team of <em>developers</em> and <em>designers</em>. 9 sections: 10 blogs: 11 title_html: <h3>Blogs & publications</h3> 12 description_html: 13 We regularly write our blog. Our blogs are covered by <strong>Ruby 14 Inside</strong> and <strong>Ruby Weekly Newsletter</strong>.
1<!-- app/views/home/index.html.erb --> 2 3<%= t('.title_html') %> 4<%= t('.description_html') %> 5 6<%= t('.sections.blogs.title_html') %> 7<%= 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.
1 2# config/locales/en.yml 3 4en: 5home: 6index: 7title_html: <h2>We build web & mobile applications</h2> 8description_html: We are a dynamic team of <em>developers</em> and <em>designers</em>. 9sections: 10blogs: 11title_html: <h3>Blogs & publications</h3> 12description_html: We regularly write our blog. Our blogs are covered by <strong>Ruby Inside</strong> and <strong>Ruby Weekly Newsletter</strong>. 13services: 14title_html: <h3>Services we offer</h3> 15list_html: - <strong>Ruby on Rails</strong> - React.js ⚛ - React Native ⚛ 📱
1 2<!-- app/views/home/index.html.erb --> 3 4<%= t('.title_html') %> 5<%= t('.description_html') %> 6 7<%= t('.sections.blogs.title_html') %> 8<%= t('.sections.blogs.description_html') %> 9 10<%= t('.sections.services.title_html') %> 11 12<ul> 13 <% t('.sections.services.list_html').each do |service| %> 14 <li><%= service %></li> 15 <% end %> 16<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.
1 2<!-- app/views/home/index.html.erb --> 3 4<%= t('.title_html') %> 5<%= t('.description_html') %> 6 7<%= t('.sections.blogs.title_html') %> 8<%= t('.sections.blogs.description_html') %> 9 10<%= t('.sections.services.title_html') %> 11 12<ul> 13 <% t('.sections.services.list_html').each do |service| %> 14 <li><%= service.html_safe %></li> 15 <% end %> 16<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.
1# config/locales/en.yml 2 3en: 4home: 5index: 6title_html: <h2>We build web & mobile applications</h2> 7description_html: We are a dynamic team of <em>developers</em> and <em>designers</em>. 8sections: 9blogs: 10title_html: <h3>Blogs & publications</h3> 11description_html: We regularly write our blog. Our blogs are covered by <strong>Ruby Inside</strong> and <strong>Ruby Weekly Newsletter</strong>. 12services: 13title_html: <h3>Services we offer</h3> 14list_html: - <strong>Ruby on Rails</strong> - React.js ⚛ - React Native ⚛ 📱
1 2<!-- app/views/home/index.html.erb --> 3 4<%= t('.title_html') %> 5<%= t('.description_html') %> 6 7<%= t('.sections.blogs.title_html') %> 8<%= t('.sections.blogs.description_html') %> 9 10<%= t('.sections.services.title_html') %> 11 12<ul> 13 <% t('.sections.services.list_html').each do |service| %> 14 <li><%= service %></li> 15 <% end %> 16<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.