From 03c419e70ce8985b2668ae5a96c08ee23965f63f Mon Sep 17 00:00:00 2001 From: Carlos Antonio da Silva Date: Fri, 13 Feb 2026 10:11:07 -0300 Subject: [PATCH] Only downcase first letter of each auth key, not the entire string (#5822) A previous change #4834 introduced a downcase call to each attribute, so that it'd fix an invalid grammar issue on some languages like English that were showing `Email` in the middle of flash message sentences. However, it caused a bug with German which uses the word `E-Mail` and at the beginning of the sentence, causing it to be converted to `E-mail` incorrectly. The fix here will only downcase the first char of each word, and convert it back to upcase at the beginning of the sentence, which should work for both the original fix (English message), and for the new bug (German message) If we end up running into any more of these edge cases with the message, we might roll it all back and provide a different set of interpolation values for the original vs downcased translations, so people can use what makes the most sense for each language without us having to manually massage these strings. Fixes #5820 --- CHANGELOG.md | 5 +++++ lib/devise/failure_app.rb | 4 +++- test/failure_app_test.rb | 5 +++++ test/support/locale/de.yml | 12 ++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 test/support/locale/de.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 38b434e1..e4e2fade 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +### Unreleased + +* bug fixes + * Fix translation issue with German `E-Mail` on invalid authentication messages caused by previous fix for incorrect grammar [#5822](https://github.com/heartcombo/devise/pull/5822) + ### 5.0.0 - 2026-01-23 no changes diff --git a/lib/devise/failure_app.rb b/lib/devise/failure_app.rb index 8222780f..1c9b5865 100644 --- a/lib/devise/failure_app.rb +++ b/lib/devise/failure_app.rb @@ -112,7 +112,9 @@ module Devise options[:default] = [message] auth_keys = scope_class.authentication_keys human_keys = (auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys).map { |key| - scope_class.human_attribute_name(key).downcase + # TODO: Remove the fallback and just use `downcase_first` once we drop support for Rails 7.0. + human_key = scope_class.human_attribute_name(key) + human_key.respond_to?(:downcase_first) ? human_key.downcase_first : human_key[0].downcase + human_key[1..] } options[:authentication_keys] = human_keys.join(I18n.t(:"support.array.words_connector")) options = i18n_options(options) diff --git a/test/failure_app_test.rb b/test/failure_app_test.rb index b57f4e42..c9e4a56c 100644 --- a/test/failure_app_test.rb +++ b/test/failure_app_test.rb @@ -215,6 +215,11 @@ class FailureTest < ActiveSupport::TestCase assert_equal 'Email ou senha inválidos.', @request.flash[:alert] assert_equal 'http://test.host/users/sign_in', @response.second["Location"] + + call_failure('warden' => OpenStruct.new(message: :invalid), 'warden.options' => { locale: :de }) + + assert_equal 'E-Mail oder Passwort ist ungültig.', @request.flash[:alert] + assert_equal 'http://test.host/users/sign_in', @response.second["Location"] end test 'uses the proxy failure message as string' do diff --git a/test/support/locale/de.yml b/test/support/locale/de.yml new file mode 100644 index 00000000..b6045716 --- /dev/null +++ b/test/support/locale/de.yml @@ -0,0 +1,12 @@ +de: + activerecord: + attributes: + user: + email: E-Mail + mongoid: + attributes: + user: + email: E-Mail + devise: + failure: + invalid: "%{authentication_keys} oder Passwort ist ungültig."