ruby-i18n / i18n

Internationalization (i18n) library for Ruby
MIT License
986 stars 411 forks source link

[BUG] Captures not respected in added interpolation patterns #578

Open aaronfrary opened 3 years ago

aaronfrary commented 3 years ago

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: https://github.com/ruby-i18n/i18n/blob/0888807ab2fe4f4c8a4b780f5654a8175df61feb/lib/i18n/interpolate/ruby.rb#L22-L23

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

aaronfrary commented 3 years ago

Is there a reason for only checking the first two capture groups here? https://github.com/ruby-i18n/i18n/blob/0888807ab2fe4f4c8a4b780f5654a8175df61feb/lib/i18n/interpolate/ruby.rb#L27

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