Posted over 2 years ago. Visible to the public. Repeats.

Dealing with I18n::InvalidPluralizationData errors

When localizing model attributes via I18n you may run into errors like this:

I18n::InvalidPluralizationData: translation data { ... } can not be used with :count => 1. key 'one' is missing.

They seem to appear out of the blue and the error message is more confusing than helpful.

TL;DR A model (e.g. Post) is lacking an attribute (e.g. thread) translation.
Fix it by adding a translation for that model's attribute ( The error message reveals the (wrongly) located I18n data (from attributes.thread).


When you run into this, you probably introduced a new model that has attributes like these:

class User < ApplicationRecord has_many :posts end
class Post < ApplicationRecord belongs_to :user validates :user, presence: true # Default for belongs_to on Rails 5+ end

I18n has the feature of falling back one level to look up translations, if it can't find one. This allows you to define common attributes like updated_at for all models on the activerecord.attributes level (or activemodel.attributes) instead of having the same translation string in each model's attribute block:

# I18n file like en.yml en: activerecord: attributes: updated_at: Last change user: name: Name role: Access level # updated_at not needed here, Rails will use the definition from above

Another feature of I18n is optional pluralization. When calling I18n.translate with a :count option, it will look for nested count instructions:

en: thing: zero: Things one: Thing other: Things

The problem

Now imagine creating a post without a user. It is invalid, and Rails will display an error message.

For generating that message, Rails will look up the post's user attribute at the level first, and fall back to the generic attributes, thus querying attributes.user. Note that this is not the user attribute, but the user model!

Now it invokes the translation with count: 1. I18n tries to pluralize the derived key (i.e. the user model, and fails. Instead of the pluralization keys one, other etc, it finds name and role.


>> nil).valid? I18n::InvalidPluralizationData: translation data {:name=>"Name", :role=>"Access level"} can not be used with :count => 1. Key 'one' is missing.

In this example, the validating the user attribute fails and Rails tries to generate localized error messages on the Post instance. The error message generator mistakenly attempts to incorporate the user model's attribute localization data and fails.


Option A: No magic (preferred)

Define translations for associations to avoid Rails' fallback to allegedly "generic". In the above example, you need to add the key Note that this is all about association names, so you must not use user_id.

# I18n file like en.yml en: activerecord: attributes: updated_at: Last change user: name: Name role: Access level post: user: Author

Option B: Use I18n internals

If applicable, you may define a "one" key for each model inside attributes, like so:

# I18n file like en.yml en: activerecord: attributes: updated_at: Last change user: one: Author name: Name role: Access level post: body: Message

While that would be possible, I am not convinced about that approach's readability.

Note that in both cases model_name.human uses the models I18n scope for resolution. You need to define your model names there.

Option C: A little magic

It might be an idea to use a Yaml reference and load all models into each model's attributes list. It will pollute your translation data with unneeded fields, though.

en: models: &models user: one: Author other: Authors post: one: Post other: Posts attributes: &attributes user: <<: *models name: Name role: Access level post: <<: *models body: Message activerecord: models: *models attributes: *attributes activemodel: models: *models attributes: *attributes

Hints for debugging

Should you still encounter the error after following the instructions above, you probably did something wrong and want to debug this further.

Place a debugger in activemodel-x.x.x/lib/active_model/errors.rb#generate_message (inside i18n you will find upper level keys only which aren't helpful anymore):

def generate_message(attribute, type = :invalid, options = {}) # many things happen here I18n.translate(key, options) rescue binding.pry end

You can then inspect the key attribute which will tell you something like:


This means the attribute user is missing for organisation/membership and can be solved by adding these lines to your translation files:

en: activerecord: attributes: organisation/membership: user: one: User other: Users

Once an application no longer requires constant development, it needs periodic maintenance for stable and secure operation. makandra offers monthly maintenance contracts that let you focus on your business while we make sure the lights stay on.

Owner of this card:

Arne Hartherz
Last edit:
over 1 year ago
by Arne Hartherz
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Arne Hartherz to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more