diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 5f1b01e01..ad57e38dc 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -10,6 +10,10 @@ nav_order: 5
## main
+* Exclude html escaping of I18n reserved keys with `I18n::RESERVED_KEYS` rather than `I18n.reserved_keys_pattern`.
+
+ *Nick Coyne*
+
* Update CI configuration to use `Appraisal`.
*Hans Lemuet, Simon Fish*
diff --git a/docs/index.md b/docs/index.md
index 24f750a5c..d68fd89cd 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -110,6 +110,7 @@ ViewComponents are Ruby objects, making it easy to follow (and enforce) code qua
ViewComponent is built by over a hundred members of the community, including:
+
diff --git a/lib/view_component/translatable.rb b/lib/view_component/translatable.rb
index 42e47eed3..422218207 100644
--- a/lib/view_component/translatable.rb
+++ b/lib/view_component/translatable.rb
@@ -138,8 +138,7 @@ def html_safe_translation(translation)
end
def html_escape_translation_options!(options)
- options.each do |name, value|
- next if ::I18n.reserved_keys_pattern.match?(name)
+ options.except(*::I18n::RESERVED_KEYS).each do |name, value|
next if name == :count && value.is_a?(Numeric)
options[name] = ERB::Util.html_escape(value.to_s)
diff --git a/test/sandbox/config/initializers/i18n.rb b/test/sandbox/config/initializers/i18n.rb
new file mode 100644
index 000000000..b99a2594c
--- /dev/null
+++ b/test/sandbox/config/initializers/i18n.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+I18n.available_locales = [:en, :fr].freeze
diff --git a/test/sandbox/test/translatable_test.rb b/test/sandbox/test/translatable_test.rb
index 7564d0c8a..3d1b7129b 100644
--- a/test/sandbox/test/translatable_test.rb
+++ b/test/sandbox/test/translatable_test.rb
@@ -75,6 +75,14 @@ def test_translate_with_html_suffix_does_not_double_escape
)
end
+ def test_translate_with_html_suffix_applies_reserved_options
+ translation = translate(".hello_html", locale: :fr, raise: false)
+ assert_equal(
+ "Translation missing: fr.translatable_component.hello_html",
+ translation
+ )
+ end
+
def test_translate_uses_the_helper_when_no_sidecar_file_is_provided
# The cache needs to be kept clean for TranslatableComponent, otherwise it will rely on the
# already created i18n_backend.