diff --git a/CHANGELOG.md b/CHANGELOG.md index 4db83a17..e4444b62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ * Put a whitespace before the `inline_label` options of boolean input if it is present. * Add support to configure the `label_text` proc at the wrapper level. [@NOX73](https://github.com/NOX73) * `label_text` proc now receive three arguments (label, request, and if the label was explicit). [@timscott](https://github.com/timscott) + * Add I18n support to `:include_blank` and `:prompt` when `:translate` is used as value. [@haines](https://github.com/plataformatec/simple_form/pull/616) ### bug fix * Collection input that uses automatic collection translation properly sets checked values. diff --git a/README.md b/README.md index ded0ab9a..f817fbca 100644 --- a/README.md +++ b/README.md @@ -611,7 +611,7 @@ end ## I18n -**Simple Form** uses all power of I18n API to lookup labels, hints and placeholders. To customize your +**Simple Form** uses all power of I18n API to lookup labels, hints, prompts and placeholders. To customize your forms you can create a locale file like this: ```yaml @@ -629,12 +629,18 @@ en: user: username: 'Your username' password: '****' + include_blanks: + user: + age: 'Rather not say' + prompts: + gender: + age: 'Select your gender' ``` And your forms will use this information to render the components for you. -**Simple Form** also lets you be more specific, separating lookups through actions for labels, hints and -placeholders. Let's say you want a different label for new and edit actions, the locale file would +**Simple Form** also lets you be more specific, separating lookups through actions. +Let's say you want a different label for new and edit actions, the locale file would be something like: ```yaml @@ -673,13 +679,19 @@ en: ``` **Simple Form** will always look for a default attribute translation under the "defaults" key if no -specific is found inside the model key. Note that this syntax is different from 1.x. To migrate to -the new syntax, just move "labels.#{attribute}" to "labels.defaults.#{attribute}". +specific is found inside the model key. In addition, **Simple Form** will fallback to default `human_attribute_name` from Rails when no other translation is found for labels. Finally, you can also overwrite any label, hint or placeholder inside your view, just by passing the option manually. This way the I18n lookup will be skipped. +For `:prompt` and `:include_blank` the I18n lookup is optional and to enable it is necessary to pass +`:translate` as value. + +```ruby +f.input :gender, prompt: :translate +``` + **Simple Form** also has support for translating options in collection helpers. For instance, given a User with a `:gender` attribute, you might want to create a select box showing translated labels that would post either `male` or `female` as value. With **Simple Form** you could create an input diff --git a/lib/generators/simple_form/templates/config/locales/simple_form.en.yml b/lib/generators/simple_form/templates/config/locales/simple_form.en.yml index 9810cea1..23743833 100644 --- a/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +++ b/lib/generators/simple_form/templates/config/locales/simple_form.en.yml @@ -10,7 +10,7 @@ en: # html: '*' error_notification: default_message: "Please review the problems below:" - # Labels and hints examples + # Examples # labels: # defaults: # password: 'Password' @@ -23,3 +23,9 @@ en: # defaults: # username: 'User name to sign in.' # password: 'No special characters, please.' + # include_blanks: + # defaults: + # age: 'Rather not say' + # prompts: + # defaults: + # age: 'Select your age' diff --git a/lib/simple_form/inputs/collection_input.rb b/lib/simple_form/inputs/collection_input.rb index 4c1410a0..e3ec5058 100644 --- a/lib/simple_form/inputs/collection_input.rb +++ b/lib/simple_form/inputs/collection_input.rb @@ -19,7 +19,13 @@ module SimpleForm def input_options options = super + options[:include_blank] = true unless skip_include_blank? + + [:prompt, :include_blank].each do |key| + translate_option options, key + end + options end @@ -99,7 +105,14 @@ module SimpleForm true end end + + def translate_option(options, key) + if options[key] == :translate + namespace = key.to_s.pluralize + + options[key] = translate(namespace, true) + end + end end end end - diff --git a/test/inputs/collection_select_input_test.rb b/test/inputs/collection_select_input_test.rb index 74fba5c4..90c33222 100644 --- a/test/inputs/collection_select_input_test.rb +++ b/test/inputs/collection_select_input_test.rb @@ -31,7 +31,7 @@ class CollectionSelectInputTest < ActionView::TestCase test 'input should do automatic collection translation for select types using defaults key' do store_translations(:en, simple_form: { options: { defaults: { gender: { male: 'Male', female: 'Female'} - } } } ) do + } } }) do with_input_for @user, :gender, :select, collection: [:male, :female] assert_select 'select.select#user_gender' assert_select 'select option', 'Male' @@ -42,7 +42,7 @@ class CollectionSelectInputTest < ActionView::TestCase test 'input should do automatic collection translation for select types using specific object key' do store_translations(:en, simple_form: { options: { user: { gender: { male: 'Male', female: 'Female'} - } } } ) do + } } }) do with_input_for @user, :gender, :select, collection: [:male, :female] assert_select 'select.select#user_gender' assert_select 'select option', 'Male' @@ -102,9 +102,63 @@ class CollectionSelectInputTest < ActionView::TestCase assert_select 'select option[value=]', '' end + test 'input should translate include blank when set to :translate' do + store_translations(:en, simple_form: { include_blanks: { user: { + age: 'Rather not say' + } } }) do + with_input_for @user, :age, :select, collection: 18..30, include_blank: :translate + assert_select 'select option[value=]', 'Rather not say' + end + end + + test 'input should translate include blank with a default' do + store_translations(:en, simple_form: { include_blanks: { defaults: { + age: 'Rather not say', + } } }) do + with_input_for @user, :age, :select, collection: 18..30, include_blank: :translate + assert_select 'select option[value=]', 'Rather not say' + end + end + + test 'input should not translate include blank when set to a string' do + store_translations(:en, simple_form: { include_blanks: { user: { + age: 'Rather not say' + } } }) do + with_input_for @user, :age, :select, collection: 18..30, include_blank: 'Young at heart' + assert_select 'select option[value=]', 'Young at heart' + end + end + + test 'input should not translate include blank when automatically set' do + store_translations(:en, simple_form: { include_blanks: { user: { + age: 'Rather not say' + } } }) do + with_input_for @user, :age, :select, collection: 18..30 + assert_select 'select option[value=]', '' + end + end + + test 'input should not translate include blank when set to true' do + store_translations(:en, simple_form: { include_blanks: { user: { + age: 'Rather not say' + } } }) do + with_input_for @user, :age, :select, collection: 18..30, include_blank: true + assert_select 'select option[value=]', '' + end + end + + test 'input should not translate include blank when set to false' do + store_translations(:en, simple_form: { include_blanks: { user: { + age: 'Rather not say' + } } }) do + with_input_for @user, :age, :select, collection: 18..30, include_blank: false + assert_no_select 'select option[value=]' + end + end + test 'input should not set include blank if otherwise is told' do with_input_for @user, :age, :select, collection: 18..30, include_blank: false - assert_no_select 'select option[value=]', '' + assert_no_select 'select option[value=]' end test 'input should not set include blank if prompt is given' do @@ -117,6 +171,51 @@ class CollectionSelectInputTest < ActionView::TestCase assert_no_select 'select option[value=]', '' end + test 'input should translate prompt when set to :translate' do + store_translations(:en, simple_form: { prompts: { user: { + age: 'Select age:' + } } }) do + with_input_for @user, :age, :select, collection: 18..30, prompt: :translate + assert_select 'select option[value=]', 'Select age:' + end + end + + test 'input should translate prompt with a default' do + store_translations(:en, simple_form: { prompts: { defaults: { + age: 'Select age:', + } } }) do + with_input_for @user, :age, :select, collection: 18..30, prompt: :translate + assert_select 'select option[value=]', 'Select age:' + end + end + + test 'input should not translate prompt when set to a string' do + store_translations(:en, simple_form: { prompts: { user: { + age: 'Select age:' + } } }) do + with_input_for @user, :age, :select, collection: 18..30, prompt: 'Do it:' + assert_select 'select option[value=]', 'Do it:' + end + end + + test 'input should not translate prompt when set to false' do + store_translations(:en, simple_form: { prompts: { user: { + age: 'Select age:' + } } }) do + with_input_for @user, :age, :select, collection: 18..30, prompt: false + assert_no_select 'select option[value=]' + end + end + + test 'input should use Rails prompt translation as a fallback' do + store_translations(:en, helpers: { select: { + prompt: 'Select value:' + } }) do + with_input_for @user, :age, :select, collection: 18..30, prompt: :translate + assert_select 'select option[value=]', "Select value:" + end + end + test 'input should detect label and value on collections' do users = [User.build(id: 1, name: "Jose"), User.build(id: 2, name: "Carlos")] with_input_for @user, :description, :select, collection: users