Ruby/Rails i18n does not (per 2025-07-07) respect the HTML-safety of interpolated values, so you need to do this:
I18n.t("foo.bar", link: link_to("Help", help_path)).html_safe
Even though link_to
returns a html_safe?
string, it will be escaped unless we flag the entire string as safe.
Flagging the whole string is at best inelegant, but also opens up for XSS injection attacks.
Less likely, a translator will inject evil HTML into the translation strings themselves. (But they should not be able to, however unlikely.)
More likely, you interpolate multiple values and accidentally trust all of them:
I18n.t("foo.bar", customer: customer.name, link: link_to("Help", help_path)).html_safe
This Gist has code for a t_html_safely
method that behaves in a safer way.
In a view:
t_html_safely(".foo", link: link_to("Help", help_path))
Outside of a view:
I18nHelper.t_html_safely("foo", link: a_html_safe_string)