Skip to content

Commit 0e0194a

Browse files
committed
Handle missing attributes for AM::Translation#human_attribute_name
```ruby require "bundler/inline" gemfile(true) do source "https://rubygems.org" #gem "rails", "~>7.0.0" gem "rails", "~>7.2.0" gem "sqlite3" # Rails 7.0 deps: #gem "sqlite3", "~>1.4" #gem "timeout", "~>0.1" #gem "securerandom" #gem "concurrent-ruby", "1.3.4" end require "active_record" require "minitest/autorun" require "logger" ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT) I18n.backend.store_translations( :ja, { activerecord: { attributes: { "post/status": { draft: 'draft in Japanese', published: 'published in Japanese', }, "post/author": { name: "Name in Japanese" } } } } ) ActiveRecord::Schema.define do create_table :posts, force: true do |t| t.integer :status end create_table :authors, force: true do |t| t.string :name end end class Post < ActiveRecord::Base enum :status, draft: 0, published: 1 belongs_to :author end class BugTest < ActiveSupport::TestCase def test_association_stuff value = nil assert_nothing_raised { Post.human_attribute_name("status.#{value}", {locale: :ja}) } attr = Post.human_attribute_name("status.#{value}", {locale: :ja}) assert_equal "Status", attr assert_nothing_raised { Post.human_attribute_name("author.name", {locale: :ja}) } attr = Post.human_attribute_name("author.name", {locale: :ja}) assert_equal "Name in Japanese", attr end end ``` Raises `I18n::InvalidPluralizationData`: ``` 1) Error: BugTest#test_association_stuff: I18n::InvalidPluralizationData: translation data {:draft=>"draft in Japanese", :published=>"published in Japanese"} can not be used with :count => 1. key 'one' is missing. /home/zzak/.rbenv/versions/3.3.6/lib/ruby/gems/3.3.0/gems/i18n-1.14.6/lib/i18n/backend/base.rb:187:in `pluralize' /home/zzak/.rbenv/versions/3.3.6/lib/ruby/gems/3.3.0/gems/i18n-1.14.6/lib/i18n/backend/base.rb:50:in `translate' /home/zzak/.rbenv/versions/3.3.6/lib/ruby/gems/3.3.0/gems/i18n-1.14.6/lib/i18n.rb:394:in `block in translate_key' /home/zzak/.rbenv/versions/3.3.6/lib/ruby/gems/3.3.0/gems/i18n-1.14.6/lib/i18n.rb:393:in `catch' /home/zzak/.rbenv/versions/3.3.6/lib/ruby/gems/3.3.0/gems/i18n-1.14.6/lib/i18n.rb:393:in `translate_key' /home/zzak/.rbenv/versions/3.3.6/lib/ruby/gems/3.3.0/gems/i18n-1.14.6/lib/i18n.rb:223:in `translate' bug.rb:87:in `translate' /home/zzak/.rbenv/versions/3.3.6/lib/ruby/gems/3.3.0/gems/activemodel-7.2.2.1/lib/active_model/translation.rb:67:in `human_attribute_name' bug.rb:98:in `block in test_association_stuff' /home/zzak/.rbenv/versions/3.3.6/lib/ruby/gems/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/testing/assertions.rb:49:in `assert_nothing_raised' bug.rb:98:in `test_association_stuff' 1 runs, 0 assertions, 0 failures, 1 errors, 0 skips ```
1 parent 94729d0 commit 0e0194a

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

activemodel/lib/active_model/translation.rb

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,19 @@ def human_attribute_name(attribute, options = {})
5252
namespace, _, attribute = attribute.rpartition(".")
5353
namespace.tr!(".", "/")
5454

55+
if attribute.present?
56+
key = "#{namespace}.#{attribute}"
57+
separator = "/"
58+
else
59+
key = namespace
60+
separator = "."
61+
end
62+
5563
defaults = lookup_ancestors.map do |klass|
56-
:"#{i18n_scope}.attributes.#{klass.model_name.i18n_key}/#{namespace}.#{attribute}"
64+
:"#{i18n_scope}.attributes.#{klass.model_name.i18n_key}#{separator}#{key}"
5765
end
58-
defaults << :"#{i18n_scope}.attributes.#{namespace}.#{attribute}"
66+
defaults << :"#{i18n_scope}.attributes.#{key}"
67+
defaults << :"attributes.#{key}"
5968
else
6069
defaults = lookup_ancestors.map do |klass|
6170
:"#{i18n_scope}.attributes.#{klass.model_name.i18n_key}.#{attribute}"
@@ -69,7 +78,9 @@ def human_attribute_name(attribute, options = {})
6978
defaults << MISSING_TRANSLATION unless raise_on_missing
7079

7180
translation = I18n.translate(defaults.shift, count: 1, raise: raise_on_missing, **options, default: defaults)
72-
translation = attribute.humanize if translation == MISSING_TRANSLATION
81+
if translation == MISSING_TRANSLATION
82+
translation = attribute.present? ? attribute.humanize : namespace.humanize
83+
end
7384
translation
7485
end
7586
end

activemodel/test/cases/translation_test.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ def test_translated_subclass_model_when_ancestor_translation
104104
assert_equal "person model", Child.model_name.human
105105
end
106106

107+
def test_translated_attributes_when_nil
108+
I18n.backend.store_translations "en", activemodel: { attributes: { "person/addresses": { street: "Person Address Street" } } }
109+
assert_equal("Addresses", Person.human_attribute_name("addresses.#{nil}"))
110+
end
111+
112+
def test_translated_deeply_nested_attributes_when_nil
113+
I18n.backend.store_translations "en", activemodel: { attributes: { "person/contacts/addresses": { street: "Deeply Nested Address Street" } } }
114+
assert_equal("Addresses/contacts", Person.human_attribute_name("addresses.contacts.#{nil}"))
115+
end
116+
107117
def test_translated_subclass_model_when_missing_translation
108118
assert_equal "Child", Child.model_name.human
109119
end

0 commit comments

Comments
 (0)