Context: For a Ruby on Rails app for bike rentals, I am using the gem globalize to deal with input :description
in different languages.
Curent state: The globalize implementation worked, depending on my locale I am able to store description
in a specific language. The input for :description
is dealt with on the basis of the locale of an entire webpage.
This means that everything on this page has to change in language in order to store :description
in the correct language.
Alternatively, I am also able to show all available locales and show description
for each of them. (See also the commented out code below).
Question: I'm searching for a way to let the user select a language for :description
only and then save :description
in the correct language without changing the language of the entire webpage.
Code
form
<div class="row">
<%# I18n.available_locales.each do |locale| %>
<!-- <h1><%#= locale %></h1> -->
<%= f.globalize_fields_for locale do |ff| %>
<div class="col-10">
<div class="form-group">
<label class="form-control-label text required" for="accommodation_category_description">Description</label>
<div><%= ff.text_area :description, :rows =>"5", :cols =>"30", class:"form-control is-valid text required" %></div>
</div>
</div>
<% end %>
<%# end %>
</div>
</div>
initializers/globalization.rb
module ActionView
module Helpers
class FormBuilder
#
# Helper that renders translations fields
# on a per-locale basis, so you can use them separately
# in the same form and still saving them all at once
# in the same request.
def globalize_fields_for(locale, *args, &proc)
raise ArgumentError, "Missing block" unless block_given?
@index = @index ? @index + 1 : 1
object_name = "#{@object_name}[translations_attributes][#{@index}]"
object = @object.translations.find_by_locale locale.to_s
@template.concat @template.hidden_field_tag("#{object_name}[id]", object ? object.id : "")
@template.concat @template.hidden_field_tag("#{object_name}[locale]", locale)
@template.fields_for(object_name, object, *args, &proc)
end
end
end
end
You can use Globalize.with_locale
to temporarily set locale, this works for views too:
<% Globalize.with_locale(some_other_locale) do %>
in this part of the page locale will be <%= locale.inspect %>
<% end %>
But for your case more user-friendly way would be to make the form dynamic, so that user can add translation for several languages of their liking.
Globalize translations are just an additional table/model YourModel::Translation
with fields for locale and translated fields, so you can work directly with these as with any other nested forms.
Add gem cocoon to your project, that will handle dynamic forms (if you're using webpacker instead of asset pipeline - that may require additional steps, to add global jquery and require js from gem using erb interpolation, see more here).
In your model:
translates :description #, ...
accepts_nested_attributes_for :translations, allow_destroy: true
in controller:
def your_some_params
params.require(:your_model_name).permit(
...
translations_attributes: [
:id, :_destroy,
:locale,
:description,
]
)
end
in form:
<div id='translations'>
<%= form.fields_for :translations do |t| %>
<%= render 'translation_fields', f: t %>
<% end %>
<div class='links'>
<%= link_to_add_association 'add translation', form, :translations %>
</div>
</div>
partial for translations like:
<div class='nested-fields'>
<%= f.hidden_field :id %>
<%= f.select :locale, I18n.available_locales %>
<%= f.text_area :description %>
<%= link_to_remove_association "remove this translation", f %>
</div>