diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e6ba844..2f1de46c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ * Fix passing `format` option to `devise_for` [#5732](https://github.com/heartcombo/devise/pull/5732) * Use `ActiveRecord::SecurityUtils.secure_compare` in `Devise.secure_compare` to match two empty strings correctly. [#4829](https://github.com/heartcombo/devise/pull/4829) * Respond with `401 Unauthorized` for non-navigational requests to destroy the session when there is no authenticated resource. [#4878](https://github.com/heartcombo/devise/pull/4878) + * Fix incorrect grammar of invalid authentication message with capitalized attributes, e.g.: "Invalid Email or password" => "Invalid email or password". (originally introduced by [#4014](https://github.com/heartcombo/devise/pull/4014), released on v4.1.0) [#4834](https://github.com/heartcombo/devise/pull/4834) Please check [4-stable](https://github.com/heartcombo/devise/blob/4-stable/CHANGELOG.md) diff --git a/lib/devise/failure_app.rb b/lib/devise/failure_app.rb index 2f3e11e5..8222780f 100644 --- a/lib/devise/failure_app.rb +++ b/lib/devise/failure_app.rb @@ -111,13 +111,16 @@ module Devise options[:scope] = "devise.failure" options[:default] = [message] auth_keys = scope_class.authentication_keys - keys = (auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys).map { |key| scope_class.human_attribute_name(key).downcase } - options[:authentication_keys] = keys.join(I18n.t(:"support.array.words_connector")) + human_keys = (auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys).map { |key| + scope_class.human_attribute_name(key).downcase + } + options[:authentication_keys] = human_keys.join(I18n.t(:"support.array.words_connector")) options = i18n_options(options) - translated_message = I18n.t(:"#{scope}.#{message}", **options) - # only call `#humanize` when the message is `:invalid` to ensure the original format - # of other messages - like `:does_not_exist` - is kept. - message == :invalid ? translated_message.humanize : translated_message + + I18n.t(:"#{scope}.#{message}", **options).then { |msg| + # Ensure that auth keys at the start of the translated string are properly cased. + msg.start_with?(human_keys.first) ? msg.upcase_first : msg + } else message.to_s end