ruby-i18n/i18n

Translations returned as hash when model-inflection has nested keys

Closed this issue · 17 comments

Pre 1.7.1 State

Related: #510

Our translations look something like:

activerecord:
  models:
    moose:
      one: Moose
      other: Moosen
      moose_types:
        big: Big ol moose
        ...

What I expected to happen

Moose.model_name.human(count: 2) #=> 'Moosen'

What actually happened

Moose.model_name.human(count: 2) #=> Hash
(Actually, I think this makes more sense!)

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

  • ruby 2.6
  • rails 5.2
  • i18n 1.8.1

So, it seems that our application wasn't really using model-translations idiomatically. The usage are not attributes, so they kinda got shoved in below the model-key.

If that pattern is considered wrong, this is a good forcing function towards convention (maybe it can be added to docs?). If it's an acceptable pattern, I would consider this a regression.

Happy to provide more detail/insight if required, but this seems pretty straightforward.

radar commented

The latest release of i18n is 1.8.2 and contains a fix for this issue: https://github.com/ruby-i18n/i18n/releases/tag/v1.8.2.

You’re saying you’re using 1.8.1.

@radar sounds good.

Would you say that the pattern of nesting attributes within a key meant for inflection is bad?

radar commented

Likely yes. It shouldn’t effect the performance of the library. It’s hash-based, so it’s only picking out the relevant keys as you need them. It’ll ignore other keys.

That's kind of what I'm wondering...it may have been a regression, but if it forces better patterns, I'm for it. 👍
In either case, thanks for being so responsive and helpful!

❤️

@radar can confirm this still caused the same issues in 1.8.2.

radar commented

I am unable to reproduce this in a new Rails application. Please provide an application that reliably reproduces the issue with any version of Rails, and I18n 1.8.2.

@chevinbrown Unfortunately, there is still in error in 1.8.2

When you use the following locale file content:

en:
  model:
    one: Single
    other: Multiple
    nested:
      broken: Broken

Then you see the following situation:

> I18n.t('model', count: 1)
{:one=>"Single", :other=>"Multiple", :nested=>{:broken=>"Broken"}}

When there is no nested information, so the nested part from the YAML is not there, then everything works.

en:
  model:
    one: Single
    other: Multiple
> I18n.t('model', count: 1)
Multiple

Do you want to have another issue for this?

@mobilutz I think you need to ping @radar 😬.
At this stage, we've taken the time to just rewrite our locales, rather than wait for a patch...so, for me, this is a closed-case, but if it's not intended, I feel like this is still the right issue.

Ryan is the maintainer though, so I'll defer to him.

radar commented

#514 (comment)

It’s a simple request, really.

@radar I reused the created app from ydkn for #510 and extended it a tiny bit.

https://github.com/mobilutz/ruby-i18n-issue-514

radar commented

This application is clearly using 1.8.1: https://github.com/mobilutz/ruby-i18n-issue-514/blob/master/Gemfile.lock#L67.

Please upgrade to 1.8.2.

bundle update i18n

I will push I18n upgrade as well.
But it does not help:

irb(main):001:0> I18n.t('activerecord.models.broken_model', count: 1)
=> {:one=>"My Model Translation", :other=>"My Models Translation", :some_other_key=>{:key=>"Value"}}
irb(main):002:0> I18n::VERSION
=> "1.8.2"
radar commented

I am able to reproduce this issue in 1.8.2, however I know of the fix.

The issue lies here:

https://github.com/ruby-i18n/i18n/blob/master/lib/i18n/backend/pluralization.rb#L34

When this line attempts to find the pluralizer logic in your application, the translation is missing and so this returns a String:

=> "translation missing: en.i18n.plural.rule"

I18n by default does not include pluralization rules because there are way too many languages, and not every application needs pluralization rules for every language.

To define the pluralization rules, we have a separate gem called rails-i18n. If you add this gem to your Gemfile, your code will work as you want it to -- as long as you're using i18n 1.8.2 too.

@radar Thanks for that information. I will definately add the additional gem to our app, to see if that solves the problem.

Can you maybe enlighten me, why version 1.7.1 (a patch version) lead to this error?

radar commented

Check out the changelog: https://github.com/ruby-i18n/i18n/releases/tag/v1.7.1

Count issue was introduced in 1.7.0 and to PATCH that issue I released 1.7.1. I don’t see a problem here.

This issue still exists in cases where the user is not using Backend::Pluralization.pluralize, but instead is using the default Backend::Base.pluralize.

The issue was introduced in #503 in both Backend::Base and Backend::Pluralization, but only reverted in Backend::Pluralization, leaving the issue in Backend::Base.

Reproducing test case (add it to test/backend/simple_test.rb)

test "simple backend translate: nested keys within pluralization context" do
  store_translations(:en,
    :stars => {
      one: "%{count} star",
      other: "%{count} stars",
      special: {
        one: "%{count} special star",
        other: "%{count} special stars",
      }
    }
  )
  assert_equal "1 star", I18n.t('stars', count: 1)
end
I18nBackendSimpleTest#test_simple_backend_translate:_nested_pluralization [test/backend/simple_test.rb:77]:
--- expected
+++ actual
@@ -1 +1 @@
-"1 star"
+{:one=>"%{count} star", :other=>"%{count} stars", :special=>{:one=>"%{count} special star", :other=>"%{count} special star"}}