From f0d1fa1ecdc6bb81bc9f3898c7b57b2031bec6c0 Mon Sep 17 00:00:00 2001 From: Laura Eck Date: Sat, 29 Sep 2018 10:12:50 +0900 Subject: [PATCH] Fix crash when available locales are enforced but fallback locale unavailable (#1796) --- CHANGELOG.md | 1 + README.md | 2 + lib/grape/exceptions/base.rb | 10 ++++- spec/grape/exceptions/base_spec.rb | 61 ++++++++++++++++++++++++++++++ spec/spec_helper.rb | 4 +- 5 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 spec/grape/exceptions/base_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 9312324e60..70b91a4cb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ #### Fixes * Your contribution here. +* [#1796](https://github.com/ruby-grape/grape/pull/1796): Fix crash when available locales are enforced but fallback locale unavailable - [@Morred](https://github.com/Morred). * [#1776](https://github.com/ruby-grape/grape/pull/1776): Validate response returned by the exception handler - [@darren987469](https://github.com/darren987469). * [#1787](https://github.com/ruby-grape/grape/pull/1787): Add documented but not implemented ability to `.insert` a middleware in the stack - [@michaellennox](https://github.com/michaellennox). * [#1788](https://github.com/ruby-grape/grape/pull/1788): Fix route requirements bug - [@darren987469](https://github.com/darren987469), [@darrellnash](https://github.com/darrellnash). diff --git a/README.md b/README.md index 94e80896d5..20e6bf11cc 100644 --- a/README.md +++ b/README.md @@ -1559,6 +1559,8 @@ end Grape supports I18n for parameter-related error messages, but will fallback to English if translations for the default locale have not been provided. See [en.yml](lib/grape/locale/en.yml) for message keys. +In case your app enforces available locales only and :en is not included in your available locales, Grape cannot fall back to English and will return the translation key for the error message. To avoid this behaviour, either provide a translation for your default locale or add :en to your available locales. + ### Custom Validation messages Grape supports custom validation messages for parameter-related and coerce-related error messages. diff --git a/lib/grape/exceptions/base.rb b/lib/grape/exceptions/base.rb index d54fe6efea..82ddbae69f 100644 --- a/lib/grape/exceptions/base.rb +++ b/lib/grape/exceptions/base.rb @@ -74,7 +74,15 @@ def translate(key, **options) options = options.dup options[:default] &&= options[:default].to_s message = ::I18n.translate(key, **options) - message.present? ? message : ::I18n.translate(key, locale: FALLBACK_LOCALE, **options) + message.present? ? message : fallback_message(key, **options) + end + + def fallback_message(key, **options) + if ::I18n.enforce_available_locales && !::I18n.available_locales.include?(FALLBACK_LOCALE) + key + else + ::I18n.translate(key, locale: FALLBACK_LOCALE, **options) + end end end end diff --git a/spec/grape/exceptions/base_spec.rb b/spec/grape/exceptions/base_spec.rb new file mode 100644 index 0000000000..e793740f3b --- /dev/null +++ b/spec/grape/exceptions/base_spec.rb @@ -0,0 +1,61 @@ +require 'spec_helper' + +describe Grape::Exceptions::Base do + describe '#compose_message' do + subject { described_class.new.send(:compose_message, key, attributes) } + + let(:key) { :invalid_formatter } + let(:attributes) { { klass: String, to_format: 'xml' } } + + after do + I18n.available_locales = %i[en] + I18n.default_locale = :en + end + + context 'when I18n enforces available locales' do + before { I18n.enforce_available_locales = true } + + context 'when the fallback locale is available' do + before do + I18n.available_locales = %i[de en] + I18n.default_locale = :de + end + + it 'returns the translated message' do + expect(subject).to eq('cannot convert String to xml') + end + end + + context 'when the fallback locale is not available' do + before do + I18n.available_locales = %i[de jp] + I18n.default_locale = :de + end + + it 'returns the translation string' do + expect(subject).to eq("grape.errors.messages.#{key}") + end + end + end + + context 'when I18n does not enforce available locales' do + before { I18n.enforce_available_locales = false } + + context 'when the fallback locale is available' do + before { I18n.available_locales = %i[de en] } + + it 'returns the translated message' do + expect(subject).to eq('cannot convert String to xml') + end + end + + context 'when the fallback locale is not available' do + before { I18n.available_locales = %i[de jp] } + + it 'returns the translated message' do + expect(subject).to eq('cannot convert String to xml') + end + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e00fba2281..9baf9bf57c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -12,7 +12,9 @@ require file end -I18n.enforce_available_locales = false +# The default value for this setting is true in a standard Rails app, +# so it should be set to true here as well to reflect that. +I18n.enforce_available_locales = true RSpec.configure do |config| config.include Rack::Test::Methods