Skip to content

Commit

Permalink
Merge pull request #682 from tom-lord/add_I18n.interpolation_keys
Browse files Browse the repository at this point in the history
Add I18n.interpolation_keys
  • Loading branch information
radar committed May 6, 2024
2 parents 9b84d1d + 40aef98 commit 73fd07e
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
40 changes: 40 additions & 0 deletions lib/i18n.rb
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,35 @@ def translate!(key, **options)
end
alias :t! :translate!

# Returns an array of interpolation keys for the given translation key
#
# *Examples*
#
# Suppose we have the following:
# I18n.t 'example.zero' == 'Zero interpolations'
# I18n.t 'example.one' == 'One interpolation %{foo}'
# I18n.t 'example.two' == 'Two interpolations %{foo} %{bar}'
# I18n.t 'example.three' == ['One %{foo}', 'Two %{bar}', 'Three %{baz}']
# I18n.t 'example.one', locale: :other == 'One interpolation %{baz}'
#
# Then we can expect the following results:
# I18n.interpolation_keys('example.zero') #=> []
# I18n.interpolation_keys('example.one') #=> ['foo']
# I18n.interpolation_keys('example.two') #=> ['foo', 'bar']
# I18n.interpolation_keys('example.three') #=> ['foo', 'bar', 'baz']
# I18n.interpolation_keys('one', scope: 'example', locale: :other) #=> ['baz']
# I18n.interpolation_keys('does-not-exist') #=> []
# I18n.interpolation_keys('example') #=> []
def interpolation_keys(key, **options)
raise I18n::ArgumentError if !key.is_a?(String) || key.empty?

return [] unless exists?(key, **options.slice(:locale, :scope))

translation = translate(key, **options.slice(:locale, :scope))
interpolation_keys_from_translation(translation)
.flatten.compact
end

# Returns true if a translation exists for a given key, otherwise returns false.
def exists?(key, _locale = nil, locale: _locale, **options)
locale ||= config.locale
Expand Down Expand Up @@ -429,6 +458,17 @@ def normalize_key(key, separator)
keys
end
end

def interpolation_keys_from_translation(translation)
case translation
when ::String
translation.scan(Regexp.union(I18n.config.interpolation_patterns))
when ::Array
translation.map { |element| interpolation_keys_from_translation(element) }
else
[]
end
end
end

extend Base
Expand Down
28 changes: 28 additions & 0 deletions test/i18n_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,34 @@ def setup
assert_equal I18n.config.available_locales.size * 2, I18n.config.available_locales_set.size
end

test "interpolation_keys returns an array of keys" do
store_translations(:en, "example_two" => "Two interpolations %{foo} %{bar}")
assert_equal ["foo", "bar"], I18n.interpolation_keys("example_two")
end

test "interpolation_keys returns an empty array when no interpolations " do
store_translations(:en, "example_zero" => "Zero interpolations")
assert_equal [], I18n.interpolation_keys("example_zero")
end

test "interpolation_keys returns an empty array when missing translation " do
assert_equal [], I18n.interpolation_keys("does-not-exist")
end

test "interpolation_keys returns an empty array when nested translation" do
store_translations(:en, "example_nested" => { "one" => "One %{foo}", "two" => "Two %{bar}" })
assert_equal [], I18n.interpolation_keys("example_nested")
end

test "interpolation_keys returns an array of keys when translation is an Array" do
store_translations(:en, "example_array" => ["One %{foo}", ["Two %{bar}", ["Three %{baz}"]]])
assert_equal ["foo", "bar", "baz"], I18n.interpolation_keys("example_array")
end

test "interpolation_keys raises I18n::ArgumentError when non-string argument" do
assert_raises(I18n::ArgumentError) { I18n.interpolation_keys(["bad-argument"]) }
end

test "exists? given an existing key will return true" do
assert_equal true, I18n.exists?(:currency)
end
Expand Down

0 comments on commit 73fd07e

Please sign in to comment.