diff --git a/actionview/lib/action_view/helpers/translation_helper.rb b/actionview/lib/action_view/helpers/translation_helper.rb index c9e328933e..89f984bc7f 100644 --- a/actionview/lib/action_view/helpers/translation_helper.rb +++ b/actionview/lib/action_view/helpers/translation_helper.rb @@ -96,9 +96,13 @@ module ActionView end end + html_safe_options[:default] = MISSING_TRANSLATION unless html_safe_options[:default].blank? + translation = I18n.translate(fully_resolved_key, **html_safe_options.merge(raise: i18n_raise)) - if translation.respond_to?(:map) + if translation.equal?(MISSING_TRANSLATION) + translated_text = options[:default].first + elsif translation.respond_to?(:map) translated_text = translation.map { |element| element.respond_to?(:html_safe) ? element.html_safe : element } else translated_text = translation.respond_to?(:html_safe) ? translation.html_safe : translation @@ -150,6 +154,9 @@ module ActionView alias :l :localize private + MISSING_TRANSLATION = Object.new + private_constant :MISSING_TRANSLATION + def scope_key_by_partial(key) stringified_key = key.to_s if stringified_key.start_with?(".") diff --git a/actionview/test/template/translation_helper_test.rb b/actionview/test/template/translation_helper_test.rb index 7d3ecb8441..9b0b2e3faa 100644 --- a/actionview/test/template/translation_helper_test.rb +++ b/actionview/test/template/translation_helper_test.rb @@ -247,6 +247,13 @@ class TranslationHelperTest < ActiveSupport::TestCase assert_equal false, translation.html_safe? end + def test_translate_does_not_mark_unsourced_string_default_as_html_safe + untrusted_string = "" + translation = translate(:"translations.missing", default: [:"translations.missing_html", untrusted_string]) + assert_equal untrusted_string, translation + assert_not_predicate translation, :html_safe? + end + def test_translate_with_string_default translation = translate(:'translations.missing', default: "A Generic String") assert_equal "A Generic String", translation