ruby-i18n/i18n

[BUG] Captures not respected in added interpolation patterns

aaronfrary opened this issue · 1 comments

What I tried to do

Added a new interpolation pattern and called #interpolate:

require 'i18n'
I18n.config.interpolation_patterns << /\$\((\w+)\)/
I18n.interpolate('Example $(interp) text', interp: 'interpolated')

What I expected to happen

Expected it to return "Example interpolated text".

What actually happened

/Users/aaronfrary/.rvm/gems/ruby-3.0.1/gems/i18n-1.8.10/lib/i18n/config.rb:99:
in `block in missing_interpolation_argument_handler':
missing interpolation argument :"$(interp)" in "Example $(interp) text"
({:interp=>"interpolated"} given) (I18n::MissingInterpolationArgument)

Looks like it failed to use the capture group between the $( and ) and instead used the whole match. I think this could be related to the use of Regexp.union here:

def interpolate_hash(string, values)
string.gsub(Regexp.union(config.interpolation_patterns)) do |match|

From the docs:

The behavior is unspecified if any given pattern contains capture.

Versions of i18n, rails, and anything else you think is necessary

i18n version 1.8.10

Is there a reason for only checking the first two capture groups here?

key = ($1 || $2 || match.tr("%{}", "")).to_sym

Seems like you could use something like Regexp.last_match.captures.compact.first to get a capture group more reliably.