ruby-i18n / i18n

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

[BUG] `Symbol` resolving interpolates the string multiple times #599

Open movermeyer opened 2 years ago

movermeyer commented 2 years ago

What I tried to do

# frozen_string_literal: true

require "i18n"

I18n.backend = I18n::Backend::Simple.new
I18n.backend.store_translations(:en, foo: :bar, bar: "%{baz}")
puts(I18n.t("foo", baz: "%{qux}"))

What I expected to happen

"%{qux}"

i.e., the resolved Symbol's value is only interpolated once and returned.

What actually happened

I18n::MissingInterpolationArgument: missing interpolation argument :qux in "%{qux}" ({:baz=>"%{qux}"} given)

This is a result of %{baz} interpolating to %{qux}, and then the code trying to interpolate %{qux}.

Note that removing the Symbol resolving works:

# frozen_string_literal: true

require "i18n"

I18n.backend = I18n::Backend::Simple.new
I18n.backend.store_translations(:en, foo: "%{baz}")
puts(I18n.t("foo", baz: "%{qux}"))

Note that interpolation occurs for each layer of Symbol resolving that is done:

e.g.,

# frozen_string_literal: true

require "i18n"

I18n.backend = I18n::Backend::Simple.new
I18n.backend.store_translations(:en, foo: :bar, bar: :baz, baz: "%{baz}")
puts(I18n.t("foo", baz: "%{qux}", qux: "%{cat}"))

Interpolates the string three times.

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

i18n: v1.8.11
Ruby: v3.0.3
movermeyer commented 2 years ago

This can also happen as a result of Symbol resolving via default parameters:

# frozen_string_literal: true

require "i18n"

I18n.backend = I18n::Backend::Simple.new
I18n.backend.store_translations(:en, foo: "%{baz}")
puts(I18n.t("non-existent", baz: "%{qux}", default: [:foo]))
alexpls commented 1 month ago

@movermeyer I reckon this'll have been resolved now with https://github.com/ruby-i18n/i18n/pull/699 being merged.