September 11, 2019
This blog is part of our Rails 6 series.
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>
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.
If this blog was helpful, check out our full blog archive.