Skip to content

Commit a5247bb

Browse files
rafaelfrancaderarugavingmiller
authored
Treat html suffix in controller translation
There are some difference between translation in a view and translation in a controller. This will treat html suffix in controller translation. Closes rails#27862. Co-authored-by: Rui Onodera <[email protected]> Co-authored-by: Gavin Miller <[email protected]>
1 parent 5e1a039 commit a5247bb

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

actionpack/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
* Treat html suffix in controller translation.
2+
3+
*Rui Onodera*, *Gavin Miller*
4+
15
* Allow permitting numeric params.
26

37
Previously it was impossible to permit different fields on numeric parameters.

actionpack/lib/abstract_controller/translation.rb

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,20 @@ def translate(key, **options)
2222
end
2323

2424
i18n_raise = options.fetch(:raise, self.raise_on_missing_translations)
25-
I18n.translate(key, **options, raise: i18n_raise)
25+
26+
if html_safe_translation_key?(key)
27+
html_safe_options = options.dup
28+
options.except(*I18n::RESERVED_KEYS).each do |name, value|
29+
unless name == :count && value.is_a?(Numeric)
30+
html_safe_options[name] = ERB::Util.html_escape(value.to_s)
31+
end
32+
end
33+
translation = I18n.translate(key, **html_safe_options, raise: i18n_raise)
34+
35+
translation.respond_to?(:html_safe) ? translation.html_safe : translation
36+
else
37+
I18n.translate(key, **options, raise: i18n_raise)
38+
end
2639
end
2740
alias :t :translate
2841

@@ -31,5 +44,10 @@ def localize(object, **options)
3144
I18n.localize(object, **options)
3245
end
3346
alias :l :localize
47+
48+
private
49+
def html_safe_translation_key?(key)
50+
/(\b|_|\.)html$/.match?(key.to_s)
51+
end
3452
end
3553
end

actionpack/test/abstract/translation_test.rb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ def setup
2020
translation: {
2121
index: {
2222
foo: "bar",
23+
hello: "<a>Hello World</a>",
24+
hello_html: "<a>Hello World</a>",
25+
interpolated_html: "<a>Hello %{word}</a>",
26+
nested: { html: "<a>nested</a>" }
2327
},
2428
no_action: "no_action_tr",
2529
},
@@ -95,6 +99,43 @@ def test_localize
9599
assert_equal expected, @controller.l(time)
96100
end
97101
end
102+
103+
def test_translate_does_not_mark_plain_text_as_safe_html
104+
@controller.stub :action_name, :index do
105+
translation = @controller.t(".hello")
106+
assert_equal "<a>Hello World</a>", translation
107+
assert_equal false, translation.html_safe?
108+
end
109+
end
110+
111+
def test_translate_marks_translations_with_a_html_suffix_as_safe_html
112+
@controller.stub :action_name, :index do
113+
translation = @controller.t(".hello_html")
114+
assert_equal "<a>Hello World</a>", translation
115+
assert_equal true, translation.html_safe?
116+
end
117+
end
118+
119+
def test_translate_marks_translation_with_nested_html_key
120+
@controller.stub :action_name, :index do
121+
translation = @controller.t(".nested.html")
122+
assert_equal "<a>nested</a>", translation
123+
assert_equal true, translation.html_safe?
124+
end
125+
end
126+
127+
def test_translate_escapes_interpolations_in_translations_with_a_html_suffix
128+
word_struct = Struct.new(:to_s)
129+
@controller.stub :action_name, :index do
130+
translation = @controller.t(".interpolated_html", word: "<World>")
131+
assert_equal "<a>Hello &lt;World&gt;</a>", translation
132+
assert_equal true, translation.html_safe?
133+
134+
translation = @controller.t(".interpolated_html", word: word_struct.new("<World>"))
135+
assert_equal "<a>Hello &lt;World&gt;</a>", translation
136+
assert_equal true, translation.html_safe?
137+
end
138+
end
98139
end
99140
end
100141
end

0 commit comments

Comments
 (0)