Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add I18n.interpolation_keys #682

Merged
merged 5 commits into from
May 6, 2024

Conversation

tom-lord
Copy link
Contributor

@tom-lord tom-lord commented Mar 1, 2024

Adds a new method, I18n.interpolation_keys, which returns a list of keys needed to fully resolve a translation.

Some 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') #=> []

In a recent project, I wanted to be able to figure out "What keys are needed for this translation"?
To my surprise, there wasn't a built-in method for this in I18n; the only option was to hand-roll some regex to look for %{...} patterns in the translation.

So now I've tried to implement it here "properly", making use of I18n.config.interpolation_patterns to be more robust with how interpolations are identified by the library -- e.g. it will also match %<foo>.d by default, and respect custom pattern configurations like {{foo}}.

lib/i18n.rb Show resolved Hide resolved
@radar
Copy link
Collaborator

radar commented Mar 4, 2024

In a recent project, I wanted to be able to figure out "What keys are needed for this translation"?

I'd be keen to know what this project is :) It sounds a little in the vein of LocaleApp, etc.

I think the feature is lightweight enough and it could be useful for others. Please do add some tests here.

end

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could raise an exception or return nil, but in the interest of simplicity and consistency, I feel it's probably fine to return [].

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think [] is better here as it makes the return type consistently Array rather than Array | nil


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")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this scenario, I18n.t("example_nested") does not require/use any interpolation keys (even though the child translations do). Therefore I feel it's correct for the method to return [].

when ::String
translation.scan(Regexp.union(I18n.config.interpolation_patterns))
when ::Array
translation.map { |element| interpolation_keys_from_translation(element) }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this does need to be recursive!

@tom-lord tom-lord marked this pull request as ready for review March 24, 2024 00:09
@tom-lord tom-lord force-pushed the add_I18n.interpolation_keys branch from 5362318 to 7559fef Compare March 24, 2024 00:21
@tom-lord
Copy link
Contributor Author

@radar Sorry for the slow progress, I was on holiday 😄

I've gone through some more edge cases, added more documentation and tests. Please take a look when you have time!

@tom-lord
Copy link
Contributor Author

tom-lord commented Mar 24, 2024

I'd be keen to know what this project is :) It sounds a little in the vein of LocaleApp, etc.

I did have applications like that in mind when proposing to push this feature into the main I18n project. However, my specific problem was a bit more granular:

In an application, translations may or may not utilise interpolation keys, in each locale. Sometimes, resolving those keys is an "expensive" operation. So as an optimisation, it makes sense to skip trying to resolve any keys that aren't actually being used.

@radar radar merged commit 73fd07e into ruby-i18n:master May 6, 2024
@radar
Copy link
Collaborator

radar commented May 6, 2024

Thanks!

@tom-lord tom-lord deleted the add_I18n.interpolation_keys branch May 28, 2024 12:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants