Как использовать i18n с рельсами 4 перечисления
рельсы 4 Перечисления Активных Записей велики, но каков правильный шаблон для перевода с i18n?
16 ответов:
Я также не нашел никакого конкретного шаблона, поэтому я просто добавил:
en: user_status: active: Active pending: Pending... archived: Archived
на произвольный .yml-файл. Тогда, на мой взгляд:
I18n.t :"user_status.#{user.status}"
начиная с Rails 5, все модели наследуют от
ApplicationRecord
.class User < ApplicationRecord enum status: [:active, :pending, :archived] end
Я использую этот суперкласс для реализации общего решения для перевода перечислений:
class ApplicationRecord < ActiveRecord::Base self.abstract_class = true def self.human_enum_name(enum_name, enum_value) I18n.t("activerecord.attributes.#{model_name.i18n_key}.#{enum_name.to_s.pluralize}.#{enum_value}") end end
затем я добавляю переводы в мой
.yml
file:en: activerecord: attributes: user: statuses: active: "Active" pending: "Pending" archived: "Archived"
наконец, чтобы получить перевод, я использую:
User.human_enum_name(:status, :pending) => "Pending"
вот такой вид:
select_tag :gender, options_for_select(Profile.gender_attributes_for_select)
вот модель (вы можете переместить этот код в хелпер или декоратор)
class Profile < ActiveRecord::Base enum gender: {male: 1, female: 2, trans: 3} # @return [Array<Array>] def self.gender_attributes_for_select genders.map do |gender, _| [I18n.t("activerecord.attributes.#{model_name.i18n_key}.genders.#{gender}"), gender] end end end
и вот файл локали:
en: activerecord: attributes: profile: genders: male: Male female: Female trans: Trans
чтобы интернационализация была похожа на любой другой атрибут, я следовал вложенному атрибуту, как вы можете видеть здесь.
если у вас есть класс
User
:class User < ActiveRecord::Base enum role: [ :teacher, :coordinator ] end
и
yml
такой:pt-BR: activerecord: attributes: user/role: # You need to nest the values under model_name/attribute_name coordinator: Coordenador teacher: Professor
вы можете использовать:
User.human_attribute_name("role.#{@user.role}")
модель:
enum stage: { starting: 1, course: 2, ending: 3 } def self.i18n_stages(hash = {}) stages.keys.each { |key| hash[I18n.t("checkpoint_stages.#{key}")] = key } hash end
Locale:
checkpoint_stages: starting: Saída course: Percurso ending: Chegada
и на вид (.slim):
= f.input_field :stage, collection: Checkpoint.i18n_stages, as: :radio_buttons
разрабатывая ответ user3647358, вы можете сделать это очень близко к тому, к чему вы привыкли при переводе имен атрибутов.
Locale file:
en: activerecord: attributes: profile: genders: male: Male female: Female trans: Trans
перевести, позвонив I18n#t:
profile = Profile.first I18n.t(profile.gender, scope: [:activerecord, :attributes, :profile, :genders])
Я создал драгоценный камень для этого.
http://rubygems.org/gems/translated_attribute_value
добавить в свой gemfile:
gem 'translated_attribute_value'
Если у вас есть поле статус пользователя:
pt-BR: activerecord: attributes: user: status_translation: value1: 'Translation for value1' value2: 'Translation for value2'
и на ваш взгляд вы можете позвонить так:
user.status_translated
Он работает с активной записью, mongoid или любым другим классом с геттер/сеттеры:
попробуйте использовать TranslateEnum камень для этих целей
class Post < ActiveRecord::Base enum status: { published: 0, archive: 1 } translate_enum :status end Post.translated_status(:published) Post.translated_statuses @post = Post.new(status: :published) @post.translated_status
объединение ответов от Repolês и Александр, для Rails 5 мы можем построить 2 метода, которые позволяют перевести одно значение или коллекцию значений из атрибута enum.
настройка переводов в вашем
.yml
file:en: activerecord: attributes: user: statuses: active: "Active" pending: "Pending" archived: "Archived"
на
ApplicationRecord
класс, от которого наследуются все модели, мы определяем метод, который обрабатывает переводы для одного значения и другой, который обрабатывает массивы путем вызова это:class ApplicationRecord < ActiveRecord::Base self.abstract_class = true def self.translate_enum_name(enum_name, enum_value) I18n.t("activerecord.attributes.#{model_name.i18n_key}.#{enum_name.to_s.pluralize}.#{enum_value}") end def self.translate_enum_collection(enum_name) enum_values = self.send(enum_name.to_s.pluralize).keys enum_values.map do |enum_value| self.translate_enum_name enum_name, enum_value end end end
в наших представлениях, мы можем перевести отдельные значения:
<p>User Status: <%= User.translate_enum_name :status, @user.status %></p>
или вся коллекция значений перечисления:
<%= f.select(:status, User.translate_enum_collection :status) %>
попробовать enum_help камень. Из его описания:
справка ActiveRecord:: Enum функция для работы нормально с I18n и simple_form.
здесь
t_enum
вспомогательный метод, который я использую.<%= t_enum(@user, :status) %>
enum_helper.РБ:
module EnumHelper def t_enum(inst, enum) value = inst.send(enum); t_enum_class(inst.class, enum, value) end def t_enum_class(klass, enum, value) unless value.blank? I18n.t("activerecord.enums.#{klass.to_s.demodulize.underscore}.#{enum}.#{value}") end end end
пользователей.РБ:
class User < ActiveRecord::Base enum status: [:active, :pending, :archived] end
ванной.в формате YML:
en: activerecord: enums: user: status: active: "Active" pending: "Pending..." archived: "Archived"
модель:
class User < ActiveRecord::Base enum role: [:master, :apprentice] end
файл язык:
en: activerecord: attributes: user: master: Master apprentice: Apprentice
использование:
User.human_attribute_name(:master) # => Master User.human_attribute_name(:apprentice) # => Apprentice
Я предпочитаю простой помощник в application_helper
def translate_enum(object, enum_name) I18n.t("activerecord.attributes.#{object.model_name.i18n_key}.#{enum_name.to_s.pluralize}.#{object.send(enum_name)}") end
затем в моем файле YML:
fr: activerecord: attributes: my_model: my_enum_plural: pending: "En cours" accepted: "Accepté" refused: "Refusé"
еще один способ, я нахожу его немного более удобным, используя озабоченность в моделях
относятся :
module EnumTranslation extend ActiveSupport::Concern def t_enum(enum) I18n.t "activerecord.attributes.#{self.class.name.underscore}.enums.#{enum}.#{self.send(enum)}" end end
YML:
fr: activerecord: attributes: campaign: title: Titre short_description: Description courte enums: status: failed: "Echec"
View:
<% @campaigns.each do |c| %> <%= c.t_enum("status") %> <% end %>
Не забудьте добавить беспокойство в вашей модели:
class Campaign < ActiveRecord::Base include EnumTranslation enum status: [:designed, :created, :active, :failed, :success] end
вы можете просто добавить помощника:
def my_something_list modes = 'activerecord.attributes.mymodel.my_somethings' I18n.t(modes).map {|k, v| [v, k]} end
и настроить его, как обычно:
en: activerecord: attributes: mymodel: my_somethings: my_enum_value: "My enum Value!"
затем используйте его с помощью select:
my_something_list
class ApplicationRecord < ActiveRecord::Base self.abstract_class = true def self.enum(definitions) defind_i18n_text(definitions) if definitions.delete(:_human) super(definitions) end def self.defind_i18n_text(definitions) scope = i18n_scope definitions.each do |name, values| next if name.to_s.start_with?('_') define_singleton_method("human_#{name.to_s.tableize}") do p values values.map { |key, _value| [key, I18n.t("#{scope}.enums.#{model_name.i18n_key}.#{name}.#{key}")] }.to_h end define_method("human_#{name}") do I18n.t("#{scope}.enums.#{model_name.i18n_key}.#{name}.#{send(name)}") end end end end en: activerecord: enums: mymodel: my_somethings: my_enum_value: "My enum Value!" enum status: [:unread, :down], _human: true