port5432
port5432

Reputation: 6381

options_for_select and i18n

Our Rails app has a list of valid language code stored in an array.

LANGUAGES = [:en,:fr,:es,:tr,:pt,:de,:it,:ga,:gr]

The are translated via a locales file.

  en: 'English'
  de: 'German'
  ga: 'Irish'
  fr: 'French'
  etc.

I would like to display the translated string in options_for_select, but this code is passing the translated value to the controller, eg: 'French'.

<%= f.select :language, options_for_select(t(LanguageName::LANGUAGES), f.object.language || t('fr')) %>

Note that this select will default the select to 'fr' only if it is not already populated.

Upvotes: 0

Views: 1540

Answers (1)

yihyang
yihyang

Reputation: 111

Referring to the document here: https://apidock.com/rails/v3.2.8/ActionView/Helpers/FormOptionsHelper/options_for_select

options_for_select({ "Basic" => "$20", "Plus" => "$40" }, "$40")
  <option value="$20">Basic</option>\n<option value="$40" selected="selected">Plus</option>

Assuming in your locale file the name of the languages is as follows:

en:
  languages:
    en: 'English'
    de: 'German'
    ga: 'Irish'
    fr: 'French'

I'm thinking what you need is something like the following:

f.select :language, options_for_select(
  LanguageName::LANGUAGES.map { |lang| [t("languages.#{lang}"), lang] }.to_h
  f.object.language || t('languages.fr')
)

Of course it's always better to extract the method out into a helper file:

class ApplicationHelper
  def map_locale_names(locale)
    LanguageName::LANGUAGES.map { |lang| [t("languages.#{lang}", locale: locale), lang] }.to_h
  end
end

so that your method will become the following:

f.select :language, options_for_select(
  map_locale_names(locale: params[:locale]),
  f.object.language || t('languages.fr')
)

Hope this helps.

Upvotes: 1

Related Questions